mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Implement scratchpad
Implements the following commands: * move scratchpad * scratchpad show * [criteria] scratchpad show Also fixes these: * Fix memory leak when executing command with criteria (use `list_free(views)` instead of `free(views)`) * Fix crash when running `move to` with no further arguments
This commit is contained in:
		
							parent
							
								
									89dc047ca9
								
							
						
					
					
						commit
						81e8f31cc6
					
				
					 13 changed files with 290 additions and 5 deletions
				
			
		
							
								
								
									
										26
									
								
								include/sway/scratchpad.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								include/sway/scratchpad.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -48,6 +48,8 @@ struct sway_server {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_t *transactions;
 | 
						list_t *transactions;
 | 
				
			||||||
	list_t *dirty_containers;
 | 
						list_t *dirty_containers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_t *scratchpad; // struct sway_container
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_server server;
 | 
					struct sway_server server;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,11 @@ struct sway_container {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_container *parent;
 | 
						struct sway_container *parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Indicates that the container is a scratchpad container.
 | 
				
			||||||
 | 
						// Both hidden and visible scratchpad containers have scratchpad=true.
 | 
				
			||||||
 | 
						// Hidden scratchpad containers have a NULL parent.
 | 
				
			||||||
 | 
						bool scratchpad;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float alpha;
 | 
						float alpha;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_texture *title_focused;
 | 
						struct wlr_texture *title_focused;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +149,7 @@ static struct cmd_handler command_handlers[] = {
 | 
				
			||||||
	{ "reload", cmd_reload },
 | 
						{ "reload", cmd_reload },
 | 
				
			||||||
	{ "rename", cmd_rename },
 | 
						{ "rename", cmd_rename },
 | 
				
			||||||
	{ "resize", cmd_resize },
 | 
						{ "resize", cmd_resize },
 | 
				
			||||||
 | 
						{ "scratchpad", cmd_scratchpad },
 | 
				
			||||||
	{ "split", cmd_split },
 | 
						{ "split", cmd_split },
 | 
				
			||||||
	{ "splith", cmd_splith },
 | 
						{ "splith", cmd_splith },
 | 
				
			||||||
	{ "splitt", cmd_splitt },
 | 
						{ "splitt", cmd_splitt },
 | 
				
			||||||
| 
						 | 
					@ -326,7 +327,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
 | 
				
			||||||
	} while(head);
 | 
						} while(head);
 | 
				
			||||||
cleanup:
 | 
					cleanup:
 | 
				
			||||||
	free(exec);
 | 
						free(exec);
 | 
				
			||||||
	free(views);
 | 
						list_free(views);
 | 
				
			||||||
	if (!results) {
 | 
						if (!results) {
 | 
				
			||||||
		results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
							results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include "sway/input/cursor.h"
 | 
					#include "sway/input/cursor.h"
 | 
				
			||||||
#include "sway/input/seat.h"
 | 
					#include "sway/input/seat.h"
 | 
				
			||||||
#include "sway/output.h"
 | 
					#include "sway/output.h"
 | 
				
			||||||
 | 
					#include "sway/scratchpad.h"
 | 
				
			||||||
#include "sway/tree/arrange.h"
 | 
					#include "sway/tree/arrange.h"
 | 
				
			||||||
#include "sway/tree/container.h"
 | 
					#include "sway/tree/container.h"
 | 
				
			||||||
#include "sway/tree/layout.h"
 | 
					#include "sway/tree/layout.h"
 | 
				
			||||||
| 
						 | 
					@ -296,6 +297,19 @@ static struct cmd_results *move_to_position(struct sway_container *container,
 | 
				
			||||||
	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct cmd_results *move_to_scratchpad(struct sway_container *con) {
 | 
				
			||||||
 | 
						if (con->type != C_CONTAINER && con->type != C_VIEW) {
 | 
				
			||||||
 | 
							return cmd_results_new(CMD_INVALID, "move",
 | 
				
			||||||
 | 
									"Only views and containers can be moved to the scratchpad");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (con->scratchpad) {
 | 
				
			||||||
 | 
							return cmd_results_new(CMD_INVALID, "move",
 | 
				
			||||||
 | 
									"Container is already in the scratchpad");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						scratchpad_add_container(con);
 | 
				
			||||||
 | 
						return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd_results *cmd_move(int argc, char **argv) {
 | 
					struct cmd_results *cmd_move(int argc, char **argv) {
 | 
				
			||||||
	struct cmd_results *error = NULL;
 | 
						struct cmd_results *error = NULL;
 | 
				
			||||||
	if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
 | 
						if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
 | 
				
			||||||
| 
						 | 
					@ -317,10 +331,9 @@ struct cmd_results *cmd_move(int argc, char **argv) {
 | 
				
			||||||
	} else if (strcasecmp(argv[0], "workspace") == 0) {
 | 
						} else if (strcasecmp(argv[0], "workspace") == 0) {
 | 
				
			||||||
		return cmd_move_workspace(current, argc, argv);
 | 
							return cmd_move_workspace(current, argc, argv);
 | 
				
			||||||
	} else if (strcasecmp(argv[0], "scratchpad") == 0
 | 
						} else if (strcasecmp(argv[0], "scratchpad") == 0
 | 
				
			||||||
			|| (strcasecmp(argv[0], "to") == 0
 | 
								|| (strcasecmp(argv[0], "to") == 0 && argc == 2
 | 
				
			||||||
				&& strcasecmp(argv[1], "scratchpad") == 0)) {
 | 
									&& strcasecmp(argv[1], "scratchpad") == 0)) {
 | 
				
			||||||
		// TODO: scratchpad
 | 
							return move_to_scratchpad(current);
 | 
				
			||||||
		return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
 | 
					 | 
				
			||||||
	} else if (strcasecmp(argv[0], "position") == 0) {
 | 
						} else if (strcasecmp(argv[0], "position") == 0) {
 | 
				
			||||||
		return move_to_position(current, argc, argv);
 | 
							return move_to_position(current, argc, argv);
 | 
				
			||||||
	} else if (strcasecmp(argv[0], "absolute") == 0) {
 | 
						} else if (strcasecmp(argv[0], "absolute") == 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								sway/commands/scratchpad.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								sway/commands/scratchpad.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "sway/commands.h"
 | 
				
			||||||
 | 
					#include "sway/config.h"
 | 
				
			||||||
 | 
					#include "sway/scratchpad.h"
 | 
				
			||||||
 | 
					#include "sway/server.h"
 | 
				
			||||||
 | 
					#include "sway/tree/container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct cmd_results *cmd_scratchpad(int argc, char **argv) {
 | 
				
			||||||
 | 
						struct cmd_results *error = NULL;
 | 
				
			||||||
 | 
						if ((error = checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1))) {
 | 
				
			||||||
 | 
							return error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strcmp(argv[0], "show") != 0) {
 | 
				
			||||||
 | 
							return cmd_results_new(CMD_INVALID, "scratchpad",
 | 
				
			||||||
 | 
									"Expected 'scratchpad show'");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!server.scratchpad->length) {
 | 
				
			||||||
 | 
							return cmd_results_new(CMD_INVALID, "scratchpad",
 | 
				
			||||||
 | 
									"Scratchpad is empty");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (config->handler_context.using_criteria) {
 | 
				
			||||||
 | 
							// If using criteria, this command is executed for every container which
 | 
				
			||||||
 | 
							// matches the criteria. If this container isn't in the scratchpad,
 | 
				
			||||||
 | 
							// we'll just silently return a success.
 | 
				
			||||||
 | 
							struct sway_container *con = config->handler_context.current_container;
 | 
				
			||||||
 | 
							wlr_log(WLR_INFO, "cmd_scratchpad(%s)", con->name);
 | 
				
			||||||
 | 
							if (!con->scratchpad) {
 | 
				
			||||||
 | 
								return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							scratchpad_toggle_container(con);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							scratchpad_toggle_auto();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -225,6 +225,14 @@ list_t *criteria_get_views(struct criteria *criteria) {
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	container_for_each_descendant_dfs(&root_container,
 | 
						container_for_each_descendant_dfs(&root_container,
 | 
				
			||||||
		criteria_get_views_iterator, &data);
 | 
							criteria_get_views_iterator, &data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Scratchpad items which are hidden are not in the tree.
 | 
				
			||||||
 | 
						for (int i = 0; i < server.scratchpad->length; ++i) {
 | 
				
			||||||
 | 
							struct sway_container *con = server.scratchpad->items[i];
 | 
				
			||||||
 | 
							if (!con->parent) {
 | 
				
			||||||
 | 
								criteria_get_views_iterator(con, &data);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return matches;
 | 
						return matches;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ sway_sources = files(
 | 
				
			||||||
	'debug-tree.c',
 | 
						'debug-tree.c',
 | 
				
			||||||
	'ipc-json.c',
 | 
						'ipc-json.c',
 | 
				
			||||||
	'ipc-server.c',
 | 
						'ipc-server.c',
 | 
				
			||||||
 | 
						'scratchpad.c',
 | 
				
			||||||
	'security.c',
 | 
						'security.c',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	'desktop/desktop.c',
 | 
						'desktop/desktop.c',
 | 
				
			||||||
| 
						 | 
					@ -67,6 +68,7 @@ sway_sources = files(
 | 
				
			||||||
	'commands/reload.c',
 | 
						'commands/reload.c',
 | 
				
			||||||
	'commands/rename.c',
 | 
						'commands/rename.c',
 | 
				
			||||||
	'commands/resize.c',
 | 
						'commands/resize.c',
 | 
				
			||||||
 | 
						'commands/scratchpad.c',
 | 
				
			||||||
	'commands/seat.c',
 | 
						'commands/seat.c',
 | 
				
			||||||
	'commands/seat/attach.c',
 | 
						'commands/seat/attach.c',
 | 
				
			||||||
	'commands/seat/cursor.c',
 | 
						'commands/seat/cursor.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										173
									
								
								sway/scratchpad.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								sway/scratchpad.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,173 @@
 | 
				
			||||||
 | 
					#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(server.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 < server.scratchpad->length; ++i) {
 | 
				
			||||||
 | 
							if (server.scratchpad->items[i] == con) {
 | 
				
			||||||
 | 
								list_del(server.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) {
 | 
				
			||||||
 | 
							view_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) {
 | 
				
			||||||
 | 
								// TODO: Do this properly once we can float C_CONTAINERs
 | 
				
			||||||
 | 
								if (con->type == C_VIEW) {
 | 
				
			||||||
 | 
									view_init_floating(con->sway_view);
 | 
				
			||||||
 | 
									arrange_windows(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);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						seat_set_focus(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(server.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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 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 < server.scratchpad->length; ++i) {
 | 
				
			||||||
 | 
							struct sway_container *con = server.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(server.scratchpad->length, "Scratchpad is empty")) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct sway_container *con = server.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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,8 @@ bool server_init(struct sway_server *server) {
 | 
				
			||||||
	server->dirty_containers = create_list();
 | 
						server->dirty_containers = create_list();
 | 
				
			||||||
	server->transactions = create_list();
 | 
						server->transactions = create_list();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						server->scratchpad = create_list();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	input_manager = input_manager_create(server);
 | 
						input_manager = input_manager_create(server);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -135,6 +137,7 @@ void server_fini(struct sway_server *server) {
 | 
				
			||||||
	wl_display_destroy(server->wl_display);
 | 
						wl_display_destroy(server->wl_display);
 | 
				
			||||||
	list_free(server->dirty_containers);
 | 
						list_free(server->dirty_containers);
 | 
				
			||||||
	list_free(server->transactions);
 | 
						list_free(server->transactions);
 | 
				
			||||||
 | 
						list_free(server->scratchpad);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool server_start_backend(struct sway_server *server) {
 | 
					bool server_start_backend(struct sway_server *server) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@
 | 
				
			||||||
#include "sway/input/seat.h"
 | 
					#include "sway/input/seat.h"
 | 
				
			||||||
#include "sway/ipc-server.h"
 | 
					#include "sway/ipc-server.h"
 | 
				
			||||||
#include "sway/output.h"
 | 
					#include "sway/output.h"
 | 
				
			||||||
 | 
					#include "sway/scratchpad.h"
 | 
				
			||||||
#include "sway/server.h"
 | 
					#include "sway/server.h"
 | 
				
			||||||
#include "sway/tree/arrange.h"
 | 
					#include "sway/tree/arrange.h"
 | 
				
			||||||
#include "sway/tree/layout.h"
 | 
					#include "sway/tree/layout.h"
 | 
				
			||||||
| 
						 | 
					@ -328,6 +329,10 @@ static struct sway_container *container_destroy_noreaping(
 | 
				
			||||||
	con->destroying = true;
 | 
						con->destroying = true;
 | 
				
			||||||
	container_set_dirty(con);
 | 
						container_set_dirty(con);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (con->scratchpad) {
 | 
				
			||||||
 | 
							scratchpad_remove_container(con);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!con->parent) {
 | 
						if (!con->parent) {
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -955,6 +960,9 @@ void container_set_floating(struct sway_container *container, bool enable) {
 | 
				
			||||||
		container_reap_empty_recursive(workspace);
 | 
							container_reap_empty_recursive(workspace);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Returning to tiled
 | 
							// Returning to tiled
 | 
				
			||||||
 | 
							if (container->scratchpad) {
 | 
				
			||||||
 | 
								scratchpad_remove_container(container);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		container_remove_child(container);
 | 
							container_remove_child(container);
 | 
				
			||||||
		container_add_child(workspace, container);
 | 
							container_add_child(workspace, container);
 | 
				
			||||||
		container->width = container->parent->width;
 | 
							container->width = container->parent->width;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,10 @@ void container_add_child(struct sway_container *parent,
 | 
				
			||||||
	list_add(parent->children, child);
 | 
						list_add(parent->children, child);
 | 
				
			||||||
	child->parent = parent;
 | 
						child->parent = parent;
 | 
				
			||||||
	container_handle_fullscreen_reparent(child, old_parent);
 | 
						container_handle_fullscreen_reparent(child, old_parent);
 | 
				
			||||||
 | 
						if (old_parent) {
 | 
				
			||||||
 | 
							container_set_dirty(old_parent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						container_set_dirty(child);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_container *container_remove_child(struct sway_container *child) {
 | 
					struct sway_container *container_remove_child(struct sway_container *child) {
 | 
				
			||||||
| 
						 | 
					@ -153,6 +157,9 @@ struct sway_container *container_remove_child(struct sway_container *child) {
 | 
				
			||||||
	child->parent = NULL;
 | 
						child->parent = NULL;
 | 
				
			||||||
	container_notify_subtree_changed(parent);
 | 
						container_notify_subtree_changed(parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container_set_dirty(parent);
 | 
				
			||||||
 | 
						container_set_dirty(child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return parent;
 | 
						return parent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1065,7 +1065,7 @@ void view_update_marks_textures(struct sway_view *view) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool view_is_visible(struct sway_view *view) {
 | 
					bool view_is_visible(struct sway_view *view) {
 | 
				
			||||||
	if (!view->swayc || view->swayc->destroying) {
 | 
						if (!view->swayc || view->swayc->destroying || !view->swayc->parent) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_container *workspace =
 | 
						struct sway_container *workspace =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue