This creates a root.c and moves bits and pieces from elsewhere into it. * layout_init has been renamed to root_create and moved into root.c * root_destroy has been created and is called on shutdown * scratchpad code has been moved into root.c, because hidden scratchpad containers are stored in the root structmaster
							parent
							
								
									5de2223c6d
								
							
						
					
					
						commit
						04489ff420
					
				| @ -1,26 +0,0 @@ | ||||
| #ifndef _SWAY_SCRATCHPAD_H | ||||
| #define _SWAY_SCRATCHPAD_H | ||||
| 
 | ||||
| #include "tree/container.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Move a container to the scratchpad. | ||||
|  */ | ||||
| void scratchpad_add_container(struct sway_container *con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Remove a container from the scratchpad. | ||||
|  */ | ||||
| void scratchpad_remove_container(struct sway_container *con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Show or hide the next container on the scratchpad. | ||||
|  */ | ||||
| void scratchpad_toggle_auto(void); | ||||
| 
 | ||||
| /**
 | ||||
|  * Show or hide a specific container on the scratchpad. | ||||
|  */ | ||||
| void scratchpad_toggle_container(struct sway_container *con); | ||||
| 
 | ||||
| #endif | ||||
| @ -0,0 +1,57 @@ | ||||
| #ifndef _SWAY_ROOT_H | ||||
| #define _SWAY_ROOT_H | ||||
| #include <wayland-server-core.h> | ||||
| #include <wayland-util.h> | ||||
| #include <wlr/types/wlr_output_layout.h> | ||||
| #include <wlr/render/wlr_texture.h> | ||||
| #include "sway/tree/container.h" | ||||
| #include "config.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| extern struct sway_container root_container; | ||||
| 
 | ||||
| struct sway_root { | ||||
| 	struct wlr_output_layout *output_layout; | ||||
| 
 | ||||
| 	struct wl_listener output_layout_change; | ||||
| #ifdef HAVE_XWAYLAND | ||||
| 	struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link
 | ||||
| #endif | ||||
| 	struct wl_list drag_icons; // sway_drag_icon::link
 | ||||
| 
 | ||||
| 	struct wlr_texture *debug_tree; | ||||
| 
 | ||||
| 	struct wl_list outputs; // sway_output::link
 | ||||
| 
 | ||||
| 	list_t *scratchpad; // struct sway_container
 | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal new_container; | ||||
| 	} events; | ||||
| }; | ||||
| 
 | ||||
| void root_create(void); | ||||
| 
 | ||||
| void root_destroy(void); | ||||
| 
 | ||||
| /**
 | ||||
|  * Move a container to the scratchpad. | ||||
|  */ | ||||
| void root_scratchpad_add_container(struct sway_container *con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Remove a container from the scratchpad. | ||||
|  */ | ||||
| void root_scratchpad_remove_container(struct sway_container *con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Show a single scratchpad container. | ||||
|  */ | ||||
| void root_scratchpad_show(struct sway_container *con); | ||||
| 
 | ||||
| /**
 | ||||
|  * Hide a single scratchpad container. | ||||
|  */ | ||||
| void root_scratchpad_hide(struct sway_container *con); | ||||
| 
 | ||||
| #endif | ||||
| @ -1,181 +0,0 @@ | ||||
| #define _XOPEN_SOURCE 700 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdbool.h> | ||||
| #include "sway/scratchpad.h" | ||||
| #include "sway/input/seat.h" | ||||
| #include "sway/tree/arrange.h" | ||||
| #include "sway/tree/container.h" | ||||
| #include "sway/tree/view.h" | ||||
| #include "sway/tree/workspace.h" | ||||
| #include "list.h" | ||||
| #include "log.h" | ||||
| 
 | ||||
| void scratchpad_add_container(struct sway_container *con) { | ||||
| 	if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { | ||||
| 		return; | ||||
| 	} | ||||
| 	con->scratchpad = true; | ||||
| 	list_add(root_container.sway_root->scratchpad, con); | ||||
| 
 | ||||
| 	struct sway_container *parent = con->parent; | ||||
| 	container_set_floating(con, true); | ||||
| 	container_remove_child(con); | ||||
| 	arrange_windows(parent); | ||||
| 
 | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	seat_set_focus(seat, seat_get_focus_inactive(seat, parent)); | ||||
| } | ||||
| 
 | ||||
| void scratchpad_remove_container(struct sway_container *con) { | ||||
| 	if (!sway_assert(con->scratchpad, "Container is not in scratchpad")) { | ||||
| 		return; | ||||
| 	} | ||||
| 	con->scratchpad = false; | ||||
| 	for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||||
| 		if (root_container.sway_root->scratchpad->items[i] == con) { | ||||
| 			list_del(root_container.sway_root->scratchpad, i); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Show a single scratchpad container. | ||||
|  * The container might be visible on another workspace already. | ||||
|  */ | ||||
| static void scratchpad_show(struct sway_container *con) { | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	struct sway_container *ws = seat_get_focus(seat); | ||||
| 	if (ws->type != C_WORKSPACE) { | ||||
| 		ws = container_parent(ws, C_WORKSPACE); | ||||
| 	} | ||||
| 
 | ||||
|     // If the current con or any of its parents are in fullscreen mode, we
 | ||||
|     // first need to disable it before showing the scratchpad con.
 | ||||
| 	if (ws->sway_workspace->fullscreen) { | ||||
| 		container_set_fullscreen(ws->sway_workspace->fullscreen, false); | ||||
| 	} | ||||
| 
 | ||||
| 	// Show the container
 | ||||
| 	if (con->parent) { | ||||
| 		container_remove_child(con); | ||||
| 	} | ||||
| 	container_add_child(ws->sway_workspace->floating, con); | ||||
| 
 | ||||
| 	// Make sure the container's center point overlaps this workspace
 | ||||
| 	double center_lx = con->x + con->width / 2; | ||||
| 	double center_ly = con->y + con->height / 2; | ||||
| 
 | ||||
| 	struct wlr_box workspace_box; | ||||
| 	container_get_box(ws, &workspace_box); | ||||
| 	if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { | ||||
| 		// Maybe resize it
 | ||||
| 		if (con->width > ws->width || con->height > ws->height) { | ||||
| 			container_init_floating(con); | ||||
| 		} | ||||
| 
 | ||||
| 		// Center it
 | ||||
| 		double new_lx = ws->x + (ws->width - con->width) / 2; | ||||
| 		double new_ly = ws->y + (ws->height - con->height) / 2; | ||||
| 		container_floating_move_to(con, new_lx, new_ly); | ||||
| 	} | ||||
| 
 | ||||
| 	arrange_windows(ws); | ||||
| 	seat_set_focus(seat, seat_get_focus_inactive(seat, con)); | ||||
| 
 | ||||
| 	container_set_dirty(con->parent); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Hide a single scratchpad container. | ||||
|  * The container might not be the focused container (eg. when using criteria). | ||||
|  */ | ||||
| static void scratchpad_hide(struct sway_container *con) { | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	struct sway_container *focus = seat_get_focus(seat); | ||||
| 	struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||||
| 
 | ||||
| 	container_remove_child(con); | ||||
| 	arrange_windows(ws); | ||||
| 	if (con == focus) { | ||||
| 		seat_set_focus(seat, seat_get_focus_inactive(seat, ws)); | ||||
| 	} | ||||
| 	list_move_to_end(root_container.sway_root->scratchpad, con); | ||||
| } | ||||
| 
 | ||||
| void scratchpad_toggle_auto(void) { | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	struct sway_container *focus = seat_get_focus(seat); | ||||
| 	struct sway_container *ws = focus->type == C_WORKSPACE ? | ||||
| 		focus : container_parent(focus, C_WORKSPACE); | ||||
| 
 | ||||
| 	// If the focus is in a floating split container,
 | ||||
| 	// operate on the split container instead of the child.
 | ||||
| 	if (container_is_floating_or_child(focus)) { | ||||
| 		while (focus->parent->layout != L_FLOATING) { | ||||
| 			focus = focus->parent; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
|     // Check if the currently focused window is a scratchpad window and should
 | ||||
|     // be hidden again.
 | ||||
| 	if (focus->scratchpad) { | ||||
| 		wlr_log(WLR_DEBUG, "Focus is a scratchpad window - hiding %s", | ||||
| 				focus->name); | ||||
| 		scratchpad_hide(focus); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     // Check if there is an unfocused scratchpad window on the current workspace
 | ||||
|     // and focus it.
 | ||||
| 	for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) { | ||||
| 		struct sway_container *floater = | ||||
| 			ws->sway_workspace->floating->children->items[i]; | ||||
| 		if (floater->scratchpad && focus != floater) { | ||||
| 			wlr_log(WLR_DEBUG, | ||||
| 					"Focusing other scratchpad window (%s) in this workspace", | ||||
| 					floater->name); | ||||
| 			scratchpad_show(floater); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|     // Check if there is a visible scratchpad window on another workspace.
 | ||||
|     // In this case we move it to the current workspace.
 | ||||
| 	for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||||
| 		struct sway_container *con = | ||||
| 			root_container.sway_root->scratchpad->items[i]; | ||||
| 		if (con->parent) { | ||||
| 			wlr_log(WLR_DEBUG, | ||||
| 					"Moving a visible scratchpad window (%s) to this workspace", | ||||
| 					con->name); | ||||
| 			scratchpad_show(con); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Take the container at the bottom of the scratchpad list
 | ||||
| 	if (!sway_assert(root_container.sway_root->scratchpad->length, | ||||
| 				"Scratchpad is empty")) { | ||||
| 		return; | ||||
| 	} | ||||
| 	struct sway_container *con = root_container.sway_root->scratchpad->items[0]; | ||||
| 	wlr_log(WLR_DEBUG, "Showing %s from list", con->name); | ||||
| 	scratchpad_show(con); | ||||
| } | ||||
| 
 | ||||
| void scratchpad_toggle_container(struct sway_container *con) { | ||||
| 	if (!sway_assert(con->scratchpad, "Container isn't in the scratchpad")) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     // Check if it matches a currently visible scratchpad window and hide it.
 | ||||
| 	if (con->parent) { | ||||
| 		scratchpad_hide(con); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	scratchpad_show(con); | ||||
| } | ||||
| @ -0,0 +1,147 @@ | ||||
| #define _POSIX_C_SOURCE 200809L | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <wlr/types/wlr_output_layout.h> | ||||
| #include "sway/input/seat.h" | ||||
| #include "sway/tree/arrange.h" | ||||
| #include "sway/tree/container.h" | ||||
| #include "sway/tree/root.h" | ||||
| #include "sway/tree/workspace.h" | ||||
| #include "list.h" | ||||
| #include "log.h" | ||||
| 
 | ||||
| struct sway_container root_container; | ||||
| 
 | ||||
| static void output_layout_handle_change(struct wl_listener *listener, | ||||
| 		void *data) { | ||||
| 	arrange_windows(&root_container); | ||||
| 	transaction_commit_dirty(); | ||||
| } | ||||
| 
 | ||||
| void root_create(void) { | ||||
| 	root_container.id = 0; // normally assigned in new_swayc()
 | ||||
| 	root_container.type = C_ROOT; | ||||
| 	root_container.layout = L_NONE; | ||||
| 	root_container.name = strdup("root"); | ||||
| 	root_container.instructions = create_list(); | ||||
| 	root_container.children = create_list(); | ||||
| 	root_container.current.children = create_list(); | ||||
| 	wl_signal_init(&root_container.events.destroy); | ||||
| 
 | ||||
| 	root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | ||||
| 	root_container.sway_root->output_layout = wlr_output_layout_create(); | ||||
| 	wl_list_init(&root_container.sway_root->outputs); | ||||
| #ifdef HAVE_XWAYLAND | ||||
| 	wl_list_init(&root_container.sway_root->xwayland_unmanaged); | ||||
| #endif | ||||
| 	wl_list_init(&root_container.sway_root->drag_icons); | ||||
| 	wl_signal_init(&root_container.sway_root->events.new_container); | ||||
| 	root_container.sway_root->scratchpad = create_list(); | ||||
| 
 | ||||
| 	root_container.sway_root->output_layout_change.notify = | ||||
| 		output_layout_handle_change; | ||||
| 	wl_signal_add(&root_container.sway_root->output_layout->events.change, | ||||
| 		&root_container.sway_root->output_layout_change); | ||||
| } | ||||
| 
 | ||||
| void root_destroy(void) { | ||||
| 	// sway_root
 | ||||
| 	wl_list_remove(&root_container.sway_root->output_layout_change.link); | ||||
| 	list_free(root_container.sway_root->scratchpad); | ||||
| 	wlr_output_layout_destroy(root_container.sway_root->output_layout); | ||||
| 	free(root_container.sway_root); | ||||
| 
 | ||||
| 	// root_container
 | ||||
| 	list_free(root_container.instructions); | ||||
| 	list_free(root_container.children); | ||||
| 	list_free(root_container.current.children); | ||||
| 	free(root_container.name); | ||||
| 
 | ||||
| 	memset(&root_container, 0, sizeof(root_container)); | ||||
| } | ||||
| 
 | ||||
| void root_scratchpad_add_container(struct sway_container *con) { | ||||
| 	if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { | ||||
| 		return; | ||||
| 	} | ||||
| 	con->scratchpad = true; | ||||
| 	list_add(root_container.sway_root->scratchpad, con); | ||||
| 
 | ||||
| 	struct sway_container *parent = con->parent; | ||||
| 	container_set_floating(con, true); | ||||
| 	container_remove_child(con); | ||||
| 	arrange_windows(parent); | ||||
| 
 | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	seat_set_focus(seat, seat_get_focus_inactive(seat, parent)); | ||||
| } | ||||
| 
 | ||||
| void root_scratchpad_remove_container(struct sway_container *con) { | ||||
| 	if (!sway_assert(con->scratchpad, "Container is not in scratchpad")) { | ||||
| 		return; | ||||
| 	} | ||||
| 	con->scratchpad = false; | ||||
| 	for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||||
| 		if (root_container.sway_root->scratchpad->items[i] == con) { | ||||
| 			list_del(root_container.sway_root->scratchpad, i); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void root_scratchpad_show(struct sway_container *con) { | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	struct sway_container *ws = seat_get_focus(seat); | ||||
| 	if (ws->type != C_WORKSPACE) { | ||||
| 		ws = container_parent(ws, C_WORKSPACE); | ||||
| 	} | ||||
| 
 | ||||
|     // If the current con or any of its parents are in fullscreen mode, we
 | ||||
|     // first need to disable it before showing the scratchpad con.
 | ||||
| 	if (ws->sway_workspace->fullscreen) { | ||||
| 		container_set_fullscreen(ws->sway_workspace->fullscreen, false); | ||||
| 	} | ||||
| 
 | ||||
| 	// Show the container
 | ||||
| 	if (con->parent) { | ||||
| 		container_remove_child(con); | ||||
| 	} | ||||
| 	container_add_child(ws->sway_workspace->floating, con); | ||||
| 
 | ||||
| 	// Make sure the container's center point overlaps this workspace
 | ||||
| 	double center_lx = con->x + con->width / 2; | ||||
| 	double center_ly = con->y + con->height / 2; | ||||
| 
 | ||||
| 	struct wlr_box workspace_box; | ||||
| 	container_get_box(ws, &workspace_box); | ||||
| 	if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { | ||||
| 		// Maybe resize it
 | ||||
| 		if (con->width > ws->width || con->height > ws->height) { | ||||
| 			container_init_floating(con); | ||||
| 		} | ||||
| 
 | ||||
| 		// Center it
 | ||||
| 		double new_lx = ws->x + (ws->width - con->width) / 2; | ||||
| 		double new_ly = ws->y + (ws->height - con->height) / 2; | ||||
| 		container_floating_move_to(con, new_lx, new_ly); | ||||
| 	} | ||||
| 
 | ||||
| 	arrange_windows(ws); | ||||
| 	seat_set_focus(seat, seat_get_focus_inactive(seat, con)); | ||||
| 
 | ||||
| 	container_set_dirty(con->parent); | ||||
| } | ||||
| 
 | ||||
| void root_scratchpad_hide(struct sway_container *con) { | ||||
| 	struct sway_seat *seat = input_manager_current_seat(input_manager); | ||||
| 	struct sway_container *focus = seat_get_focus(seat); | ||||
| 	struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||||
| 
 | ||||
| 	container_remove_child(con); | ||||
| 	arrange_windows(ws); | ||||
| 	if (con == focus) { | ||||
| 		seat_set_focus(seat, seat_get_focus_inactive(seat, ws)); | ||||
| 	} | ||||
| 	list_move_to_end(root_container.sway_root->scratchpad, con); | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue