Merge branch 'master' into feature/data-device-selection
This commit is contained in:
		
						commit
						a87b60e31e
					
				|  | @ -42,6 +42,7 @@ struct roots_config { | |||
| 	struct wl_list devices; | ||||
| 	struct wl_list bindings; | ||||
| 	char *config_path; | ||||
| 	char *startup_cmd; | ||||
| }; | ||||
| 
 | ||||
| struct roots_config *parse_args(int argc, char *argv[]); | ||||
|  |  | |||
|  | @ -24,18 +24,12 @@ struct roots_keyboard { | |||
| struct roots_pointer { | ||||
| 	struct roots_input *input; | ||||
| 	struct wlr_input_device *device; | ||||
| 	// We don't listen to any pointer events directly - they go through
 | ||||
| 	// wlr_cursor
 | ||||
| 	struct wl_list link; | ||||
| }; | ||||
| 
 | ||||
| struct roots_touch { | ||||
| 	struct roots_input *input; | ||||
| 	struct wlr_input_device *device; | ||||
| 	struct wl_listener down; | ||||
| 	struct wl_listener up; | ||||
| 	struct wl_listener motion; | ||||
| 	struct wl_listener cancel; | ||||
| 	struct wl_list link; | ||||
| }; | ||||
| 
 | ||||
|  | @ -82,6 +76,13 @@ struct roots_drag_icon { | |||
| 	struct wl_listener surface_commit; | ||||
| }; | ||||
| 
 | ||||
| struct roots_touch_point { | ||||
| 	struct roots_touch *device; | ||||
| 	int32_t slot; | ||||
| 	double x, y; | ||||
| 	struct wl_list link; | ||||
| }; | ||||
| 
 | ||||
| struct roots_input { | ||||
| 	struct roots_config *config; | ||||
| 	struct roots_server *server; | ||||
|  | @ -117,10 +118,17 @@ struct roots_input { | |||
| 	struct wl_listener cursor_motion_absolute; | ||||
| 	struct wl_listener cursor_button; | ||||
| 	struct wl_listener cursor_axis; | ||||
| 
 | ||||
| 	struct wl_listener cursor_touch_down; | ||||
| 	struct wl_listener cursor_touch_up; | ||||
| 	struct wl_listener cursor_touch_motion; | ||||
| 
 | ||||
| 	struct wl_listener cursor_tool_axis; | ||||
| 	struct wl_listener cursor_tool_tip; | ||||
| 
 | ||||
| 	struct wl_listener pointer_grab_begin; | ||||
| 	struct wl_list touch_points; | ||||
| 
 | ||||
| 	struct wl_listener pointer_grab_end; | ||||
| 
 | ||||
| 	struct wl_listener request_set_cursor; | ||||
|  | @ -134,6 +142,8 @@ void pointer_add(struct wlr_input_device *device, struct roots_input *input); | |||
| void pointer_remove(struct wlr_input_device *device, struct roots_input *input); | ||||
| void keyboard_add(struct wlr_input_device *device, struct roots_input *input); | ||||
| void keyboard_remove(struct wlr_input_device *device, struct roots_input *input); | ||||
| void touch_add(struct wlr_input_device *device, struct roots_input *input); | ||||
| void touch_remove(struct wlr_input_device *device, struct roots_input *input); | ||||
| void tablet_tool_add(struct wlr_input_device *device, struct roots_input *input); | ||||
| void tablet_tool_remove(struct wlr_input_device *device, struct roots_input *input); | ||||
| 
 | ||||
|  |  | |||
|  | @ -73,12 +73,14 @@ struct roots_view { | |||
| 	void (*get_size)(struct roots_view *view, struct wlr_box *box); | ||||
| 	void (*activate)(struct roots_view *view, bool active); | ||||
| 	void (*resize)(struct roots_view *view, uint32_t width, uint32_t height); | ||||
| 	void (*set_position)(struct roots_view *view, double x, double y); | ||||
| 	void (*close)(struct roots_view *view); | ||||
| }; | ||||
| 
 | ||||
| void view_get_size(struct roots_view *view, struct wlr_box *box); | ||||
| void view_activate(struct roots_view *view, bool active); | ||||
| void view_resize(struct roots_view *view, uint32_t width, uint32_t height); | ||||
| void view_set_position(struct roots_view *view, double x, double y); | ||||
| void view_close(struct roots_view *view); | ||||
| bool view_center(struct roots_view *view); | ||||
| void view_initialize(struct roots_view *view); | ||||
|  |  | |||
|  | @ -56,6 +56,9 @@ struct wlr_output { | |||
| 		struct wl_listener surface_destroy; | ||||
| 	} cursor; | ||||
| 
 | ||||
| 	// the output position in layout space reported to clients
 | ||||
| 	int32_t lx, ly; | ||||
| 
 | ||||
| 	void *data; | ||||
| }; | ||||
| 
 | ||||
|  | @ -66,6 +69,7 @@ bool wlr_output_set_mode(struct wlr_output *output, | |||
| 	struct wlr_output_mode *mode); | ||||
| void wlr_output_transform(struct wlr_output *output, | ||||
| 	enum wl_output_transform transform); | ||||
| void wlr_output_set_position(struct wlr_output *output, int32_t lx, int32_t ly); | ||||
| bool wlr_output_set_cursor(struct wlr_output *output, | ||||
| 	const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height, | ||||
| 	int32_t hotspot_x, int32_t hotspot_y); | ||||
|  |  | |||
|  | @ -16,12 +16,13 @@ | |||
| 
 | ||||
| static void usage(const char *name, int ret) { | ||||
| 	fprintf(stderr, | ||||
| 		"usage: %s [-C <FILE>]\n" | ||||
| 		"usage: %s [-C <FILE>] [-E <COMMAND>]\n" | ||||
| 		"\n" | ||||
| 		" -C <FILE>      Path to the configuration file\n" | ||||
| 		"                (default: rootston.ini).\n" | ||||
| 		"                See `rootston.ini.example` for config\n" | ||||
| 		"                file documentation.\n", name); | ||||
| 		"                file documentation.\n" | ||||
| 		" -E <COMMAND>   Command that will be ran at startup.\n" , name); | ||||
| 
 | ||||
| 	exit(ret); | ||||
| } | ||||
|  | @ -263,17 +264,24 @@ static int config_ini_handler(void *user, const char *section, const char *name, | |||
| 
 | ||||
| struct roots_config *parse_args(int argc, char *argv[]) { | ||||
| 	struct roots_config *config = calloc(1, sizeof(struct roots_config)); | ||||
| 	if (config == NULL) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	config->xwayland = true; | ||||
| 	wl_list_init(&config->outputs); | ||||
| 	wl_list_init(&config->devices); | ||||
| 	wl_list_init(&config->bindings); | ||||
| 
 | ||||
| 	int c; | ||||
| 	while ((c = getopt(argc, argv, "C:h")) != -1) { | ||||
| 	while ((c = getopt(argc, argv, "C:E:h")) != -1) { | ||||
| 		switch (c) { | ||||
| 		case 'C': | ||||
| 			config->config_path = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'E': | ||||
| 			config->startup_cmd = strdup(optarg); | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 		case '?': | ||||
| 			usage(argv[0], c != 'h'); | ||||
|  | @ -296,7 +304,8 @@ struct roots_config *parse_args(int argc, char *argv[]) { | |||
| 	int result = ini_parse(config->config_path, config_ini_handler, config); | ||||
| 
 | ||||
| 	if (result == -1) { | ||||
| 		wlr_log(L_DEBUG, "No config file found. Using empty config."); | ||||
| 		wlr_log(L_DEBUG, "No config file found. Using sensible defaults."); | ||||
| 		config->keyboard.meta_key = WLR_MODIFIER_LOGO; | ||||
| 		add_binding_config(&config->bindings, "Logo+Shift+e", "exit"); | ||||
| 		add_binding_config(&config->bindings, "Ctrl+q", "close"); | ||||
| 		add_binding_config(&config->bindings, "Alt+Tab", "next_window"); | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ | |||
| #include "rootston/config.h" | ||||
| #include "rootston/input.h" | ||||
| #include "rootston/desktop.h" | ||||
| #include "rootston/view.h" | ||||
| 
 | ||||
| const struct roots_input_event *get_input_event(struct roots_input *input, | ||||
| 		uint32_t serial) { | ||||
|  | @ -84,8 +85,8 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { | |||
| 	double sx, sy; | ||||
| 	switch (input->mode) { | ||||
| 	case ROOTS_CURSOR_PASSTHROUGH: | ||||
| 		view = view_at(desktop, input->cursor->x, input->cursor->y, &surface, | ||||
| 			&sx, &sy); | ||||
| 		view = view_at(desktop, input->cursor->x, input->cursor->y, | ||||
| 			&surface, &sx, &sy); | ||||
| 		bool set_compositor_cursor = !view && input->cursor_client; | ||||
| 		if (view) { | ||||
| 			struct wl_client *view_client = | ||||
|  | @ -106,32 +107,40 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { | |||
| 		break; | ||||
| 	case ROOTS_CURSOR_MOVE: | ||||
| 		if (input->active_view) { | ||||
| 			int dx = input->cursor->x - input->offs_x, | ||||
| 				dy = input->cursor->y - input->offs_y; | ||||
| 			input->active_view->x = input->view_x + dx; | ||||
| 			input->active_view->y = input->view_y + dy; | ||||
| 			double dx = input->cursor->x - input->offs_x; | ||||
| 			double dy = input->cursor->y - input->offs_y; | ||||
| 			view_set_position(input->active_view, | ||||
| 				input->view_x + dx, input->view_y + dy); | ||||
| 		} | ||||
| 		break; | ||||
| 	case ROOTS_CURSOR_RESIZE: | ||||
| 		if (input->active_view) { | ||||
| 			int dx = input->cursor->x - input->offs_x, | ||||
| 				dy = input->cursor->y - input->offs_y; | ||||
| 			int width = input->view_width, | ||||
| 				height = input->view_height; | ||||
| 			double dx = input->cursor->x - input->offs_x; | ||||
| 			double dy = input->cursor->y - input->offs_y; | ||||
| 			double active_x = input->active_view->x; | ||||
| 			double active_y = input->active_view->y; | ||||
| 			int width = input->view_width; | ||||
| 			int height = input->view_height; | ||||
| 			if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { | ||||
| 				input->active_view->y = input->view_y + dy; | ||||
| 				active_y = input->view_y + dy; | ||||
| 				height -= dy; | ||||
| 			} | ||||
| 			if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_BOTTOM) { | ||||
| 				height += dy; | ||||
| 			} | ||||
| 			if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) { | ||||
| 				input->active_view->x = input->view_x + dx; | ||||
| 				active_x = input->view_x + dx; | ||||
| 				width -= dx; | ||||
| 			} | ||||
| 			if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { | ||||
| 				width += dx; | ||||
| 			} | ||||
| 
 | ||||
| 			// TODO we might need one configure event for this
 | ||||
| 			if (active_x != input->active_view->x || | ||||
| 					active_y != input->active_view->y) { | ||||
| 				view_set_position(input->active_view, active_x, active_y); | ||||
| 			} | ||||
| 			view_resize(input->active_view, width, height); | ||||
| 		} | ||||
| 		break; | ||||
|  | @ -280,6 +289,56 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
| 			(uint32_t)(event->time_usec / 1000), event->button, event->state); | ||||
| } | ||||
| 
 | ||||
| static void handle_touch_down(struct wl_listener *listener, void *data) { | ||||
| 	struct wlr_event_touch_down *event = data; | ||||
| 	struct roots_input *input = | ||||
| 		wl_container_of(listener, input, cursor_touch_down); | ||||
| 	struct roots_touch_point *point = | ||||
| 		calloc(1, sizeof(struct roots_touch_point)); | ||||
| 	point->device = event->device->data; | ||||
| 	point->slot = event->slot; | ||||
| 	point->x = event->x_mm / event->width_mm; | ||||
| 	point->y = event->y_mm / event->height_mm; | ||||
| 	wlr_cursor_warp_absolute(input->cursor, event->device, point->x, point->y); | ||||
| 	cursor_update_position(input, (uint32_t)(event->time_usec / 1000)); | ||||
| 	wl_list_insert(&input->touch_points, &point->link); | ||||
| 	do_cursor_button_press(input, input->cursor, event->device, | ||||
| 			(uint32_t)(event->time_usec / 1000), BTN_LEFT, 1); | ||||
| } | ||||
| 
 | ||||
| static void handle_touch_up(struct wl_listener *listener, void *data) { | ||||
| 	struct wlr_event_touch_up *event = data; | ||||
| 	struct roots_input *input = | ||||
| 			wl_container_of(listener, input, cursor_touch_up); | ||||
| 	struct roots_touch_point *point; | ||||
| 	wl_list_for_each(point, &input->touch_points, link) { | ||||
| 		if (point->slot == event->slot) { | ||||
| 			wl_list_remove(&point->link); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	do_cursor_button_press(input, input->cursor, event->device, | ||||
| 			(uint32_t)(event->time_usec / 1000), BTN_LEFT, 0); | ||||
| } | ||||
| 
 | ||||
| static void handle_touch_motion(struct wl_listener *listener, void *data) { | ||||
| 	struct wlr_event_touch_motion *event = data; | ||||
| 	struct roots_input *input = | ||||
| 		wl_container_of(listener, input, cursor_touch_motion); | ||||
| 	struct roots_touch_point *point; | ||||
| 	wl_list_for_each(point, &input->touch_points, link) { | ||||
| 		if (point->slot == event->slot) { | ||||
| 			point->x = event->x_mm / event->width_mm; | ||||
| 			point->y = event->y_mm / event->height_mm; | ||||
| 			wlr_cursor_warp_absolute(input->cursor, event->device, | ||||
| 					point->x, point->y); | ||||
| 			cursor_update_position(input, | ||||
| 					(uint32_t)(event->time_usec / 1000)); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void handle_tool_axis(struct wl_listener *listener, void *data) { | ||||
| 	struct roots_input *input = wl_container_of(listener, input, cursor_tool_axis); | ||||
| 	struct wlr_event_tablet_tool_axis *event = data; | ||||
|  | @ -390,6 +449,9 @@ static void handle_request_set_cursor(struct wl_listener *listener, | |||
| 
 | ||||
| void cursor_initialize(struct roots_input *input) { | ||||
| 	struct wlr_cursor *cursor = input->cursor; | ||||
| 	 | ||||
| 	// TODO: Does this belong here
 | ||||
| 	wl_list_init(&input->touch_points); | ||||
| 
 | ||||
| 	wl_list_init(&input->cursor_motion.link); | ||||
| 	wl_signal_add(&cursor->events.motion, &input->cursor_motion); | ||||
|  | @ -408,6 +470,18 @@ void cursor_initialize(struct roots_input *input) { | |||
| 	wl_signal_add(&cursor->events.axis, &input->cursor_axis); | ||||
| 	input->cursor_axis.notify = handle_cursor_axis; | ||||
| 
 | ||||
| 	wl_list_init(&input->cursor_touch_down.link); | ||||
| 	wl_signal_add(&cursor->events.touch_down, &input->cursor_touch_down); | ||||
| 	input->cursor_touch_down.notify = handle_touch_down; | ||||
| 
 | ||||
| 	wl_list_init(&input->cursor_touch_up.link); | ||||
| 	wl_signal_add(&cursor->events.touch_up, &input->cursor_touch_up); | ||||
| 	input->cursor_touch_up.notify = handle_touch_up; | ||||
| 
 | ||||
| 	wl_list_init(&input->cursor_touch_motion.link); | ||||
| 	wl_signal_add(&cursor->events.touch_motion, &input->cursor_touch_motion); | ||||
| 	input->cursor_touch_motion.notify = handle_touch_motion; | ||||
| 
 | ||||
| 	wl_list_init(&input->cursor_tool_axis.link); | ||||
| 	wl_signal_add(&cursor->events.tablet_tool_axis, &input->cursor_tool_axis); | ||||
| 	input->cursor_tool_axis.notify = handle_tool_axis; | ||||
|  |  | |||
|  | @ -46,6 +46,16 @@ void view_get_size(struct roots_view *view, struct wlr_box *box) { | |||
| 	box->height = view->wlr_surface->current->height; | ||||
| } | ||||
| 
 | ||||
| void view_set_position(struct roots_view *view, double x, double y) { | ||||
| 	if (view->set_position) { | ||||
| 		view->set_position(view, x, y); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	view->x = x; | ||||
| 	view->y = y; | ||||
| } | ||||
| 
 | ||||
| void view_activate(struct roots_view *view, bool activate) { | ||||
| 	if (view->activate) { | ||||
| 		view->activate(view, activate); | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { | |||
| 		pointer_add(device, input); | ||||
| 		break; | ||||
| 	case WLR_INPUT_DEVICE_TOUCH: | ||||
| 		//touch_add(device, input);
 | ||||
| 		touch_add(device, input); | ||||
| 		break; | ||||
| 	case WLR_INPUT_DEVICE_TABLET_TOOL: | ||||
| 		tablet_tool_add(device, input); | ||||
|  | @ -58,7 +58,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { | |||
| 		pointer_remove(device, input); | ||||
| 		break; | ||||
| 	case WLR_INPUT_DEVICE_TOUCH: | ||||
| 		//touch_remove(device, input);
 | ||||
| 		touch_remove(device, input); | ||||
| 		break; | ||||
| 	case WLR_INPUT_DEVICE_TABLET_TOOL: | ||||
| 		tablet_tool_remove(device, input); | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| #define _POSIX_C_SOURCE 200112L | ||||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <wayland-server.h> | ||||
| #include <wlr/backend.h> | ||||
| #include <wlr/render.h> | ||||
|  | @ -42,6 +43,18 @@ int main(int argc, char **argv) { | |||
| 	} | ||||
| 
 | ||||
| 	setenv("WAYLAND_DISPLAY", socket, true); | ||||
| 
 | ||||
| 	if (server.config->startup_cmd != NULL) { | ||||
| 		const char *cmd = server.config->startup_cmd; | ||||
| 		pid_t pid = fork(); | ||||
| 		if (pid < 0) { | ||||
| 			wlr_log(L_ERROR, "cannot execute binding command: fork() failed"); | ||||
| 			return 1; | ||||
| 		} else if (pid == 0) { | ||||
| 			execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	wl_display_run(server.wl_display); | ||||
| 	wlr_backend_destroy(server.backend); | ||||
| 	return 0; | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ sources = [ | |||
| 	'output.c', | ||||
| 	'pointer.c', | ||||
| 	'tablet_tool.c', | ||||
| 	'touch.c', | ||||
| 	'xdg_shell_v6.c', | ||||
| 	'wl_shell.c', | ||||
| ] | ||||
|  |  | |||
|  | @ -0,0 +1,26 @@ | |||
| #include <stdlib.h> | ||||
| #include <wayland-server.h> | ||||
| #include <wlr/types/wlr_input_device.h> | ||||
| #include <wlr/types/wlr_pointer.h> | ||||
| #include "rootston/input.h" | ||||
| 
 | ||||
| // TODO: we'll likely want touch events to both control the cursor *and* be
 | ||||
| // submitted directly to the seat.
 | ||||
| 
 | ||||
| void touch_add(struct wlr_input_device *device, struct roots_input *input) { | ||||
| 	struct roots_touch *touch = calloc(sizeof(struct roots_touch), 1); | ||||
| 	device->data = touch; | ||||
| 	touch->device = device; | ||||
| 	touch->input = input; | ||||
| 	wl_list_insert(&input->touch, &touch->link); | ||||
| 	wlr_cursor_attach_input_device(input->cursor, device); | ||||
| 	cursor_load_config(input->server->config, input->cursor, | ||||
| 			input, input->server->desktop); | ||||
| } | ||||
| 
 | ||||
| void touch_remove(struct wlr_input_device *device, struct roots_input *input) { | ||||
| 	struct roots_touch *touch = device->data; | ||||
| 	wlr_cursor_detach_input_device(input->cursor, device); | ||||
| 	wl_list_remove(&touch->link); | ||||
| 	free(touch); | ||||
| } | ||||
|  | @ -109,19 +109,6 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
| 	struct roots_view *view = calloc(1, sizeof(struct roots_view)); | ||||
| 	view->type = ROOTS_WL_SHELL_VIEW; | ||||
| 
 | ||||
| 	if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { | ||||
| 		// we need to map it relative to the parent
 | ||||
| 		int i = | ||||
| 			list_seq_find(desktop->views, | ||||
| 				shell_surface_compare_equals, surface->parent); | ||||
| 		if (i != -1) { | ||||
| 			struct roots_view *parent = desktop->views->items[i]; | ||||
| 			view->x = parent->x + surface->transient_state->x; | ||||
| 			view->y = parent->y + surface->transient_state->y; | ||||
| 		} | ||||
| 	} else { | ||||
| 		view->x = view->y = 200; | ||||
| 	} | ||||
| 	view->wl_shell_surface = surface; | ||||
| 	view->roots_wl_shell_surface = roots_surface; | ||||
| 	view->wlr_surface = surface->surface; | ||||
|  | @ -131,4 +118,17 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
| 	roots_surface->view = view; | ||||
| 	list_add(desktop->views, view); | ||||
| 	view_initialize(view); | ||||
| 
 | ||||
| 	if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { | ||||
| 		// we need to map it relative to the parent
 | ||||
| 		int i = | ||||
| 			list_seq_find(desktop->views, | ||||
| 				shell_surface_compare_equals, surface->parent); | ||||
| 		if (i != -1) { | ||||
| 			struct roots_view *parent = desktop->views->items[i]; | ||||
| 			view_set_position(view, | ||||
| 				parent->x + surface->transient_state->x, | ||||
| 				parent->y + surface->transient_state->y); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -26,6 +26,15 @@ static void resize(struct roots_view *view, uint32_t width, uint32_t height) { | |||
| 		xwayland_surface->x, xwayland_surface->y, width, height); | ||||
| } | ||||
| 
 | ||||
| static void set_position(struct roots_view *view, double x, double y) { | ||||
| 	assert(view->type == ROOTS_XWAYLAND_VIEW); | ||||
| 	struct wlr_xwayland_surface *xwayland_surface = view->xwayland_surface; | ||||
| 	view->x = x; | ||||
| 	view->y = y; | ||||
| 	wlr_xwayland_surface_configure(view->desktop->xwayland, xwayland_surface, | ||||
| 		x, y, xwayland_surface->width, xwayland_surface->height); | ||||
| } | ||||
| 
 | ||||
| static void close(struct roots_view *view) { | ||||
| 	assert(view->type == ROOTS_XWAYLAND_VIEW); | ||||
| 	wlr_xwayland_surface_close(view->desktop->xwayland, view->xwayland_surface); | ||||
|  | @ -88,7 +97,12 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
| 	view->desktop = desktop; | ||||
| 	view->activate = activate; | ||||
| 	view->resize = resize; | ||||
| 	view->set_position = set_position; | ||||
| 	view->close = close; | ||||
| 	roots_surface->view = view; | ||||
| 	list_add(desktop->views, view); | ||||
| 
 | ||||
| 	if (!surface->override_redirect) { | ||||
| 		view_initialize(view); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ static void wl_output_send_to_resource(struct wl_resource *resource) { | |||
| 	assert(output); | ||||
| 	const uint32_t version = wl_resource_get_version(resource); | ||||
| 	if (version >= WL_OUTPUT_GEOMETRY_SINCE_VERSION) { | ||||
| 		wl_output_send_geometry(resource, 0, 0, // TODO: get position from layout?
 | ||||
| 		wl_output_send_geometry(resource, output->lx, output->ly, | ||||
| 			output->phys_width, output->phys_height, output->subpixel, | ||||
| 			output->make, output->model, output->transform); | ||||
| 	} | ||||
|  | @ -122,6 +122,20 @@ void wlr_output_transform(struct wlr_output *output, | |||
| 	wlr_output_update_matrix(output); | ||||
| } | ||||
| 
 | ||||
| void wlr_output_set_position(struct wlr_output *output, int32_t lx, int32_t ly) { | ||||
| 	if (lx == output->lx && ly == output->ly) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	output->lx = lx; | ||||
| 	output->ly = ly; | ||||
| 
 | ||||
| 	struct wl_resource *resource; | ||||
| 	wl_resource_for_each(resource, &output->wl_resources) { | ||||
| 		wl_output_send_to_resource(resource); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool set_cursor(struct wlr_output *output, const uint8_t *buf, | ||||
| 		int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, | ||||
| 		int32_t hotspot_y) { | ||||
|  |  | |||
|  | @ -115,6 +115,10 @@ static void wlr_output_layout_reconfigure(struct wlr_output_layout *layout) { | |||
| 		max_x += box->width; | ||||
| 	} | ||||
| 
 | ||||
| 	wl_list_for_each(l_output, &layout->outputs, link) { | ||||
| 		wlr_output_set_position(l_output->output, l_output->x, l_output->y); | ||||
| 	} | ||||
| 
 | ||||
| 	wl_signal_emit(&layout->events.change, layout); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -840,26 +840,46 @@ static const struct zxdg_surface_v6_interface zxdg_surface_v6_implementation = { | |||
| 
 | ||||
| static bool wlr_xdg_surface_v6_toplevel_state_compare( | ||||
| 		struct wlr_xdg_toplevel_v6 *state) { | ||||
| 	struct { | ||||
| 		struct wlr_xdg_toplevel_v6_state state; | ||||
| 		uint32_t width; | ||||
| 		uint32_t height; | ||||
| 
 | ||||
| 	} configured; | ||||
| 
 | ||||
| 	// is pending state different from current state?
 | ||||
| 	if (!state->base->configured) { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if (state->pending.activated != state->current.activated) { | ||||
| 	if (wl_list_empty(&state->base->configure_list)) { | ||||
| 		// last configure is actually the current state, just use it
 | ||||
| 		configured.state = state->current; | ||||
| 		configured.width = state->base->surface->current->width; | ||||
| 		configured.height = state->base->surface->current->width; | ||||
| 	} else { | ||||
| 		struct wlr_xdg_surface_v6_configure *configure = | ||||
| 			wl_container_of(state->base->configure_list.prev, configure, link); | ||||
| 		configured.state = configure->state; | ||||
| 		configured.width = configure->state.width; | ||||
| 		configured.height = configure->state.height; | ||||
| 	} | ||||
| 
 | ||||
| 	if (state->pending.activated != configured.state.activated) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (state->pending.fullscreen != state->current.fullscreen) { | ||||
| 	if (state->pending.fullscreen != configured.state.fullscreen) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (state->pending.maximized != state->current.maximized) { | ||||
| 	if (state->pending.maximized != configured.state.maximized) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (state->pending.resizing != state->current.resizing) { | ||||
| 	if (state->pending.resizing != configured.state.resizing) { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((uint32_t)state->base->geometry->width == state->pending.width && | ||||
| 			(uint32_t)state->base->geometry->height == state->pending.height) { | ||||
| 	if (state->pending.width == configured.width && | ||||
| 			state->pending.height == configured.height) { | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -947,7 +967,7 @@ static void wlr_xdg_surface_send_configure(void *user_data) { | |||
| } | ||||
| 
 | ||||
| static void wlr_xdg_surface_v6_schedule_configure( | ||||
| 		struct wlr_xdg_surface_v6 *surface, bool force) { | ||||
| 		struct wlr_xdg_surface_v6 *surface) { | ||||
| 	struct wl_display *display = wl_client_get_display(surface->client->client); | ||||
| 	struct wl_event_loop *loop = wl_display_get_event_loop(display); | ||||
| 	bool pending_same = false; | ||||
|  | @ -957,7 +977,7 @@ static void wlr_xdg_surface_v6_schedule_configure( | |||
| 		assert(0 && "not reached"); | ||||
| 		break; | ||||
| 	case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: | ||||
| 		pending_same = !force && | ||||
| 		pending_same = | ||||
| 			wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel_state); | ||||
| 		break; | ||||
| 	case WLR_XDG_SURFACE_V6_ROLE_POPUP: | ||||
|  | @ -1001,7 +1021,7 @@ static void wlr_xdg_surface_v6_toplevel_committed( | |||
| 	if (!surface->surface->texture->valid && !surface->toplevel_state->added) { | ||||
| 		// on the first commit, send a configure request to tell the client it
 | ||||
| 		// is added
 | ||||
| 		wlr_xdg_surface_v6_schedule_configure(surface, true); | ||||
| 		wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| 		surface->toplevel_state->added = true; | ||||
| 		return; | ||||
| 	} | ||||
|  | @ -1018,7 +1038,7 @@ static void wlr_xdg_surface_v6_popup_committed( | |||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP); | ||||
| 
 | ||||
| 	if (!surface->popup_state->committed) { | ||||
| 		wlr_xdg_surface_v6_schedule_configure(surface, true); | ||||
| 		wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| 		surface->popup_state->committed = true; | ||||
| 	} | ||||
| } | ||||
|  | @ -1265,49 +1285,42 @@ void wlr_xdg_surface_v6_ping(struct wlr_xdg_surface_v6 *surface) { | |||
| void wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface, | ||||
| 		uint32_t width, uint32_t height) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); | ||||
| 	bool force = | ||||
| 		(surface->toplevel_state->pending.width != width || | ||||
| 		 surface->toplevel_state->pending.height != height); | ||||
| 	surface->toplevel_state->pending.width = width; | ||||
| 	surface->toplevel_state->pending.height = height; | ||||
| 
 | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface, force); | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| } | ||||
| 
 | ||||
| void wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface, | ||||
| 		bool activated) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); | ||||
| 	bool force = surface->toplevel_state->pending.activated != activated; | ||||
| 	surface->toplevel_state->pending.activated = activated; | ||||
| 
 | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface, force); | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| } | ||||
| 
 | ||||
| void wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface, | ||||
| 		bool maximized) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); | ||||
| 	bool force = surface->toplevel_state->pending.maximized != maximized; | ||||
| 	surface->toplevel_state->pending.maximized = maximized; | ||||
| 
 | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface, force); | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| } | ||||
| 
 | ||||
| void wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface, | ||||
| 		bool fullscreen) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); | ||||
| 	bool force = surface->toplevel_state->pending.fullscreen != fullscreen; | ||||
| 	surface->toplevel_state->pending.fullscreen = fullscreen; | ||||
| 
 | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface, force); | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| } | ||||
| 
 | ||||
| void wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface, | ||||
| 		bool resizing) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); | ||||
| 	bool force = surface->toplevel_state->pending.resizing != resizing; | ||||
| 	surface->toplevel_state->pending.resizing = resizing; | ||||
| 
 | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface, force); | ||||
| 	wlr_xdg_surface_v6_schedule_configure(surface); | ||||
| } | ||||
| 
 | ||||
| void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue