mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge branch 'master' into fix-resize-wiggle
This commit is contained in:
		
						commit
						47bf4ed0cb
					
				
					 28 changed files with 529 additions and 94 deletions
				
			
		| 
						 | 
					@ -14,7 +14,9 @@ _swaymsg()
 | 
				
			||||||
    'get_marks'
 | 
					    'get_marks'
 | 
				
			||||||
    'get_bar_config'
 | 
					    'get_bar_config'
 | 
				
			||||||
    'get_version'
 | 
					    'get_version'
 | 
				
			||||||
    'get_clipboard'
 | 
					    'get_binding_modes'
 | 
				
			||||||
 | 
					    'get_config'
 | 
				
			||||||
 | 
					    'send_tick'
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  short=(
 | 
					  short=(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,9 @@ types=(
 | 
				
			||||||
'get_marks'
 | 
					'get_marks'
 | 
				
			||||||
'get_bar_config'
 | 
					'get_bar_config'
 | 
				
			||||||
'get_version'
 | 
					'get_version'
 | 
				
			||||||
 | 
					'get_binding_modes'
 | 
				
			||||||
 | 
					'get_config'
 | 
				
			||||||
 | 
					'send_tick'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_arguments -s \
 | 
					_arguments -s \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ enum ipc_command_type {
 | 
				
			||||||
	IPC_GET_VERSION = 7,
 | 
						IPC_GET_VERSION = 7,
 | 
				
			||||||
	IPC_GET_BINDING_MODES = 8,
 | 
						IPC_GET_BINDING_MODES = 8,
 | 
				
			||||||
	IPC_GET_CONFIG = 9,
 | 
						IPC_GET_CONFIG = 9,
 | 
				
			||||||
 | 
						IPC_SEND_TICK = 10,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// sway-specific command types
 | 
						// sway-specific command types
 | 
				
			||||||
	IPC_GET_INPUTS = 100,
 | 
						IPC_GET_INPUTS = 100,
 | 
				
			||||||
| 
						 | 
					@ -27,8 +28,8 @@ enum ipc_command_type {
 | 
				
			||||||
	IPC_EVENT_WINDOW = ((1<<31) | 3),
 | 
						IPC_EVENT_WINDOW = ((1<<31) | 3),
 | 
				
			||||||
	IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
 | 
						IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
 | 
				
			||||||
	IPC_EVENT_BINDING = ((1<<31) | 5),
 | 
						IPC_EVENT_BINDING = ((1<<31) | 5),
 | 
				
			||||||
	IPC_EVENT_MODIFIER = ((1<<31) | 6),
 | 
						IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
 | 
				
			||||||
	IPC_EVENT_INPUT = ((1<<31) | 7),
 | 
						IPC_EVENT_TICK = ((1<<31) | 7),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -488,8 +488,6 @@ int sway_binding_cmp_keys(const void *a, const void *b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void free_sway_binding(struct sway_binding *sb);
 | 
					void free_sway_binding(struct sway_binding *sb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_binding *sway_binding_dup(struct sway_binding *sb);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding);
 | 
					void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void load_swaybars();
 | 
					void load_swaybars();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ void seat_configure_xcursor(struct sway_seat *seat);
 | 
				
			||||||
void seat_set_focus(struct sway_seat *seat, struct sway_container *container);
 | 
					void seat_set_focus(struct sway_seat *seat, struct sway_container *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void seat_set_focus_warp(struct sway_seat *seat,
 | 
					void seat_set_focus_warp(struct sway_seat *seat,
 | 
				
			||||||
		struct sway_container *container, bool warp);
 | 
							struct sway_container *container, bool warp, bool notify);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void seat_set_focus_surface(struct sway_seat *seat,
 | 
					void seat_set_focus_surface(struct sway_seat *seat,
 | 
				
			||||||
		struct wlr_surface *surface, bool unfocus);
 | 
							struct wlr_surface *surface, bool unfocus);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,5 +16,7 @@ void ipc_event_workspace(struct sway_container *old,
 | 
				
			||||||
void ipc_event_window(struct sway_container *window, const char *change);
 | 
					void ipc_event_window(struct sway_container *window, const char *change);
 | 
				
			||||||
void ipc_event_barconfig_update(struct bar_config *bar);
 | 
					void ipc_event_barconfig_update(struct bar_config *bar);
 | 
				
			||||||
void ipc_event_mode(const char *mode, bool pango);
 | 
					void ipc_event_mode(const char *mode, bool pango);
 | 
				
			||||||
 | 
					void ipc_event_shutdown(const char *reason);
 | 
				
			||||||
 | 
					void ipc_event_binding(struct sway_binding *binding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,10 +67,18 @@ struct sway_container *output_get_active_workspace(struct sway_output *output);
 | 
				
			||||||
void output_render(struct sway_output *output, struct timespec *when,
 | 
					void output_render(struct sway_output *output, struct timespec *when,
 | 
				
			||||||
	pixman_region32_t *damage);
 | 
						pixman_region32_t *damage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void output_surface_for_each_surface(struct sway_output *output,
 | 
				
			||||||
 | 
							struct wlr_surface *surface, double ox, double oy,
 | 
				
			||||||
 | 
							sway_surface_iterator_func_t iterator, void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void output_view_for_each_surface(struct sway_output *output,
 | 
					void output_view_for_each_surface(struct sway_output *output,
 | 
				
			||||||
	struct sway_view *view, sway_surface_iterator_func_t iterator,
 | 
						struct sway_view *view, sway_surface_iterator_func_t iterator,
 | 
				
			||||||
	void *user_data);
 | 
						void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void output_view_for_each_popup(struct sway_output *output,
 | 
				
			||||||
 | 
							struct sway_view *view, sway_surface_iterator_func_t iterator,
 | 
				
			||||||
 | 
							void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void output_layer_for_each_surface(struct sway_output *output,
 | 
					void output_layer_for_each_surface(struct sway_output *output,
 | 
				
			||||||
	struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
 | 
						struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
 | 
				
			||||||
	void *user_data);
 | 
						void *user_data);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,17 +230,10 @@ struct sway_container *container_parent(struct sway_container *container,
 | 
				
			||||||
 * surface-local coordinates of the given layout coordinates if the container
 | 
					 * surface-local coordinates of the given layout coordinates if the container
 | 
				
			||||||
 * is a view and the view contains a surface at those coordinates.
 | 
					 * is a view and the view contains a surface at those coordinates.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct sway_container *container_at(struct sway_container *container,
 | 
					struct sway_container *container_at(struct sway_container *workspace,
 | 
				
			||||||
		double ox, double oy, struct wlr_surface **surface,
 | 
							double lx, double ly, struct wlr_surface **surface,
 | 
				
			||||||
		double *sx, double *sy);
 | 
							double *sx, double *sy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Same as container_at, but only checks floating views and expects coordinates
 | 
					 | 
				
			||||||
 * to be layout coordinates, as that's what floating views use.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct sway_container *floating_container_at(double lx, double ly,
 | 
					 | 
				
			||||||
		struct wlr_surface **surface, double *sx, double *sy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Apply the function for each descendant of the container breadth first.
 | 
					 * Apply the function for each descendant of the container breadth first.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,10 @@ struct sway_view_impl {
 | 
				
			||||||
	bool (*has_client_side_decorations)(struct sway_view *view);
 | 
						bool (*has_client_side_decorations)(struct sway_view *view);
 | 
				
			||||||
	void (*for_each_surface)(struct sway_view *view,
 | 
						void (*for_each_surface)(struct sway_view *view,
 | 
				
			||||||
		wlr_surface_iterator_func_t iterator, void *user_data);
 | 
							wlr_surface_iterator_func_t iterator, void *user_data);
 | 
				
			||||||
 | 
						void (*for_each_popup)(struct sway_view *view,
 | 
				
			||||||
 | 
							wlr_surface_iterator_func_t iterator, void *user_data);
 | 
				
			||||||
	void (*close)(struct sway_view *view);
 | 
						void (*close)(struct sway_view *view);
 | 
				
			||||||
 | 
						void (*close_popups)(struct sway_view *view);
 | 
				
			||||||
	void (*destroy)(struct sway_view *view);
 | 
						void (*destroy)(struct sway_view *view);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,11 +252,22 @@ void view_set_tiled(struct sway_view *view, bool tiled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_close(struct sway_view *view);
 | 
					void view_close(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_close_popups(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_damage_from(struct sway_view *view);
 | 
					void view_damage_from(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Iterate all surfaces of a view (toplevels + popups).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
void view_for_each_surface(struct sway_view *view,
 | 
					void view_for_each_surface(struct sway_view *view,
 | 
				
			||||||
	wlr_surface_iterator_func_t iterator, void *user_data);
 | 
						wlr_surface_iterator_func_t iterator, void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Iterate all popups recursively.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void view_for_each_popup(struct sway_view *view,
 | 
				
			||||||
 | 
						wlr_surface_iterator_func_t iterator, void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// view implementation
 | 
					// view implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_init(struct sway_view *view, enum sway_view_type type,
 | 
					void view_init(struct sway_view *view, enum sway_view_type type,
 | 
				
			||||||
| 
						 | 
					@ -314,6 +328,8 @@ void view_clear_marks(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool view_has_mark(struct sway_view *view, char *mark);
 | 
					bool view_has_mark(struct sway_view *view, char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_add_mark(struct sway_view *view, char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_update_marks_textures(struct sway_view *view);
 | 
					void view_update_marks_textures(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
#include <linux/input-event-codes.h>
 | 
					#include <linux/input-event-codes.h>
 | 
				
			||||||
#elif __FreeBSD__
 | 
					#elif __FreeBSD__
 | 
				
			||||||
| 
						 | 
					@ -5,9 +6,11 @@
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <xkbcommon/xkbcommon.h>
 | 
					#include <xkbcommon/xkbcommon.h>
 | 
				
			||||||
#include <xkbcommon/xkbcommon-names.h>
 | 
					#include <xkbcommon/xkbcommon-names.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include <strings.h>
 | 
					#include <strings.h>
 | 
				
			||||||
#include "sway/commands.h"
 | 
					#include "sway/commands.h"
 | 
				
			||||||
#include "sway/config.h"
 | 
					#include "sway/config.h"
 | 
				
			||||||
 | 
					#include "sway/ipc-server.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
| 
						 | 
					@ -27,6 +30,33 @@ void free_sway_binding(struct sway_binding *binding) {
 | 
				
			||||||
	free(binding);
 | 
						free(binding);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct sway_binding *sway_binding_dup(struct sway_binding *sb) {
 | 
				
			||||||
 | 
						struct sway_binding *new_sb = calloc(1, sizeof(struct sway_binding));
 | 
				
			||||||
 | 
						if (!new_sb) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new_sb->type = sb->type;
 | 
				
			||||||
 | 
						new_sb->order = sb->order;
 | 
				
			||||||
 | 
						new_sb->flags = sb->flags;
 | 
				
			||||||
 | 
						new_sb->modifiers = sb->modifiers;
 | 
				
			||||||
 | 
						new_sb->command = strdup(sb->command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new_sb->keys = create_list();
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < sb->keys->length; ++i) {
 | 
				
			||||||
 | 
							xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
 | 
				
			||||||
 | 
							if (!key) {
 | 
				
			||||||
 | 
								free_sway_binding(new_sb);
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*key = *(xkb_keysym_t *)sb->keys->items[i];
 | 
				
			||||||
 | 
							list_add(new_sb->keys, key);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return new_sb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Returns true if the bindings have the same key and modifier combinations.
 | 
					 * Returns true if the bindings have the same key and modifier combinations.
 | 
				
			||||||
 * Note that keyboard layout is not considered, so the bindings might actually
 | 
					 * Note that keyboard layout is not considered, so the bindings might actually
 | 
				
			||||||
| 
						 | 
					@ -275,11 +305,31 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
 | 
				
			||||||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
 | 
					void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "running command for binding: %s",
 | 
						wlr_log(WLR_DEBUG, "running command for binding: %s",
 | 
				
			||||||
		binding->command);
 | 
							binding->command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sway_binding *binding_copy = binding;
 | 
				
			||||||
 | 
						bool reload = false;
 | 
				
			||||||
 | 
						// if this is a reload command we need to make a duplicate of the
 | 
				
			||||||
 | 
						// binding since it will be gone after the reload has completed.
 | 
				
			||||||
 | 
						if (strcasecmp(binding->command, "reload") == 0) {
 | 
				
			||||||
 | 
							reload = true;
 | 
				
			||||||
 | 
							binding_copy = sway_binding_dup(binding);
 | 
				
			||||||
 | 
							if (!binding_copy) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "Failed to duplicate binding during reload");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config->handler_context.seat = seat;
 | 
						config->handler_context.seat = seat;
 | 
				
			||||||
	struct cmd_results *results = execute_command(binding->command, NULL);
 | 
						struct cmd_results *results = execute_command(binding->command, NULL);
 | 
				
			||||||
	if (results->status != CMD_SUCCESS) {
 | 
						if (results->status == CMD_SUCCESS) {
 | 
				
			||||||
 | 
							ipc_event_binding(binding_copy);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
 | 
							wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
 | 
				
			||||||
			binding->command, results->error);
 | 
								binding->command, results->error);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reload) { // free the binding if we made a copy
 | 
				
			||||||
 | 
							free_sway_binding(binding_copy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	free_cmd_results(results);
 | 
						free_cmd_results(results);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
 | 
				
			||||||
	view_find_and_unmark(mark);
 | 
						view_find_and_unmark(mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!toggle || !had_mark) {
 | 
						if (!toggle || !had_mark) {
 | 
				
			||||||
		list_add(view->marks, strdup(mark));
 | 
							view_add_mark(view, mark);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(mark);
 | 
						free(mark);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
 | 
				
			||||||
		container_move_to(current, destination);
 | 
							container_move_to(current, destination);
 | 
				
			||||||
		struct sway_container *focus = seat_get_focus_inactive(
 | 
							struct sway_container *focus = seat_get_focus_inactive(
 | 
				
			||||||
				config->handler_context.seat, old_parent);
 | 
									config->handler_context.seat, old_parent);
 | 
				
			||||||
		seat_set_focus(config->handler_context.seat, focus);
 | 
							seat_set_focus_warp(config->handler_context.seat, focus, true, false);
 | 
				
			||||||
		container_reap_empty(old_parent);
 | 
							container_reap_empty(old_parent);
 | 
				
			||||||
		container_reap_empty(destination->parent);
 | 
							container_reap_empty(destination->parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
 | 
				
			||||||
		struct sway_container *old_parent = current->parent;
 | 
							struct sway_container *old_parent = current->parent;
 | 
				
			||||||
		struct sway_container *old_ws = container_parent(current, C_WORKSPACE);
 | 
							struct sway_container *old_ws = container_parent(current, C_WORKSPACE);
 | 
				
			||||||
		container_move_to(current, focus);
 | 
							container_move_to(current, focus);
 | 
				
			||||||
		seat_set_focus(config->handler_context.seat, old_parent);
 | 
							seat_set_focus_warp(config->handler_context.seat, old_parent, true, false);
 | 
				
			||||||
		container_reap_empty(old_parent);
 | 
							container_reap_empty(old_parent);
 | 
				
			||||||
		container_reap_empty(focus->parent);
 | 
							container_reap_empty(focus->parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,17 +1,46 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include "sway/commands.h"
 | 
					#include "sway/commands.h"
 | 
				
			||||||
#include "sway/config.h"
 | 
					#include "sway/config.h"
 | 
				
			||||||
 | 
					#include "sway/ipc-server.h"
 | 
				
			||||||
#include "sway/tree/arrange.h"
 | 
					#include "sway/tree/arrange.h"
 | 
				
			||||||
 | 
					#include "list.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd_results *cmd_reload(int argc, char **argv) {
 | 
					struct cmd_results *cmd_reload(int argc, char **argv) {
 | 
				
			||||||
	struct cmd_results *error = NULL;
 | 
						struct cmd_results *error = NULL;
 | 
				
			||||||
	if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) {
 | 
						if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) {
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// store bar ids to check against new bars for barconfig_update events
 | 
				
			||||||
 | 
						list_t *bar_ids = create_list();
 | 
				
			||||||
 | 
						for (int i = 0; i < config->bars->length; ++i) {
 | 
				
			||||||
 | 
							struct bar_config *bar = config->bars->items[i];
 | 
				
			||||||
 | 
							list_add(bar_ids, strdup(bar->id));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!load_main_config(config->current_config_path, true)) {
 | 
						if (!load_main_config(config->current_config_path, true)) {
 | 
				
			||||||
		return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config.");
 | 
							return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config.");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ipc_event_workspace(NULL, NULL, "reload");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	load_swaybars();
 | 
						load_swaybars();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < config->bars->length; ++i) {
 | 
				
			||||||
 | 
							struct bar_config *bar = config->bars->items[i];
 | 
				
			||||||
 | 
							for (int j = 0; j < bar_ids->length; ++j) {
 | 
				
			||||||
 | 
								if (strcmp(bar->id, bar_ids->items[j]) == 0) {
 | 
				
			||||||
 | 
									ipc_event_barconfig_update(bar);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < bar_ids->length; ++i) {
 | 
				
			||||||
 | 
							free(bar_ids->items[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						list_free(bar_ids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	arrange_windows(&root_container);
 | 
						arrange_windows(&root_container);
 | 
				
			||||||
	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
 | 
				
			||||||
		data->user_data);
 | 
							data->user_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void output_surface_for_each_surface(struct sway_output *output,
 | 
					void output_surface_for_each_surface(struct sway_output *output,
 | 
				
			||||||
		struct wlr_surface *surface, double ox, double oy,
 | 
							struct wlr_surface *surface, double ox, double oy,
 | 
				
			||||||
		sway_surface_iterator_func_t iterator, void *user_data) {
 | 
							sway_surface_iterator_func_t iterator, void *user_data) {
 | 
				
			||||||
	struct surface_iterator_data data = {
 | 
						struct surface_iterator_data data = {
 | 
				
			||||||
| 
						 | 
					@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output,
 | 
				
			||||||
		output_for_each_surface_iterator, &data);
 | 
							output_for_each_surface_iterator, &data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void output_view_for_each_popup(struct sway_output *output,
 | 
				
			||||||
 | 
							struct sway_view *view, sway_surface_iterator_func_t iterator,
 | 
				
			||||||
 | 
							void *user_data) {
 | 
				
			||||||
 | 
						struct surface_iterator_data data = {
 | 
				
			||||||
 | 
							.user_iterator = iterator,
 | 
				
			||||||
 | 
							.user_data = user_data,
 | 
				
			||||||
 | 
							.output = output,
 | 
				
			||||||
 | 
							.ox = view->swayc->current.view_x - output->swayc->current.swayc_x,
 | 
				
			||||||
 | 
							.oy = view->swayc->current.view_y - output->swayc->current.swayc_y,
 | 
				
			||||||
 | 
							.width = view->swayc->current.view_width,
 | 
				
			||||||
 | 
							.height = view->swayc->current.view_height,
 | 
				
			||||||
 | 
							.rotation = 0, // TODO
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						view_for_each_popup(view, output_for_each_surface_iterator, &data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void output_layer_for_each_surface(struct sway_output *output,
 | 
					void output_layer_for_each_surface(struct sway_output *output,
 | 
				
			||||||
		struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
 | 
							struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
 | 
				
			||||||
		void *user_data) {
 | 
							void *user_data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) {
 | 
				
			||||||
	color[2] *= color[3];
 | 
						color[2] *= color[3];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void render_view_surfaces(struct sway_view *view,
 | 
					static void render_view_toplevels(struct sway_view *view,
 | 
				
			||||||
		struct sway_output *output, pixman_region32_t *damage, float alpha) {
 | 
							struct sway_output *output, pixman_region32_t *damage, float alpha) {
 | 
				
			||||||
	struct render_data data = {
 | 
						struct render_data data = {
 | 
				
			||||||
		.damage = damage,
 | 
							.damage = damage,
 | 
				
			||||||
		.alpha = alpha,
 | 
							.alpha = alpha,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	output_view_for_each_surface(output, view, render_surface_iterator, &data);
 | 
						// Render all toplevels without descending into popups
 | 
				
			||||||
 | 
						output_surface_for_each_surface(output, view->surface,
 | 
				
			||||||
 | 
								view->swayc->current.view_x, view->swayc->current.view_y,
 | 
				
			||||||
 | 
								render_surface_iterator, &data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void render_popup_iterator(struct sway_output *output,
 | 
				
			||||||
 | 
							struct wlr_surface *surface, struct wlr_box *box, float rotation,
 | 
				
			||||||
 | 
							void *data) {
 | 
				
			||||||
 | 
						// Render this popup's surface
 | 
				
			||||||
 | 
						render_surface_iterator(output, surface, box, rotation, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Render this popup's child toplevels
 | 
				
			||||||
 | 
						output_surface_for_each_surface(output, surface, box->x, box->y,
 | 
				
			||||||
 | 
								render_surface_iterator, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void render_view_popups(struct sway_view *view,
 | 
				
			||||||
 | 
							struct sway_output *output, pixman_region32_t *damage, float alpha) {
 | 
				
			||||||
 | 
						struct render_data data = {
 | 
				
			||||||
 | 
							.damage = damage,
 | 
				
			||||||
 | 
							.alpha = alpha,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						output_view_for_each_popup(output, view, render_popup_iterator, &data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void render_saved_view(struct sway_view *view,
 | 
					static void render_saved_view(struct sway_view *view,
 | 
				
			||||||
| 
						 | 
					@ -239,7 +262,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
 | 
				
			||||||
	if (view->saved_buffer) {
 | 
						if (view->saved_buffer) {
 | 
				
			||||||
		render_saved_view(view, output, damage, view->swayc->alpha);
 | 
							render_saved_view(view, output, damage, view->swayc->alpha);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		render_view_surfaces(view, output, damage, view->swayc->alpha);
 | 
							render_view_toplevels(view, output, damage, view->swayc->alpha);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->using_csd) {
 | 
						if (view->using_csd) {
 | 
				
			||||||
| 
						 | 
					@ -843,7 +866,7 @@ void output_render(struct sway_output *output, struct timespec *when,
 | 
				
			||||||
				render_saved_view(fullscreen_con->sway_view,
 | 
									render_saved_view(fullscreen_con->sway_view,
 | 
				
			||||||
						output, damage, 1.0f);
 | 
											output, damage, 1.0f);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				render_view_surfaces(fullscreen_con->sway_view,
 | 
									render_view_toplevels(fullscreen_con->sway_view,
 | 
				
			||||||
						output, damage, 1.0f);
 | 
											output, damage, 1.0f);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -879,6 +902,12 @@ void output_render(struct sway_output *output, struct timespec *when,
 | 
				
			||||||
			&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
 | 
								&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sway_seat *seat = input_manager_current_seat(input_manager);
 | 
				
			||||||
 | 
						struct sway_container *focus = seat_get_focus(seat);
 | 
				
			||||||
 | 
						if (focus && focus->type == C_VIEW) {
 | 
				
			||||||
 | 
							render_view_popups(focus->sway_view, output, damage, focus->alpha);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
render_overlay:
 | 
					render_overlay:
 | 
				
			||||||
	render_layer(output, damage,
 | 
						render_layer(output, damage,
 | 
				
			||||||
		&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
 | 
							&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view,
 | 
				
			||||||
		user_data);
 | 
							user_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void for_each_popup(struct sway_view *view,
 | 
				
			||||||
 | 
							wlr_surface_iterator_func_t iterator, void *user_data) {
 | 
				
			||||||
 | 
						if (xdg_shell_view_from_view(view) == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void _close(struct sway_view *view) {
 | 
					static void _close(struct sway_view *view) {
 | 
				
			||||||
	if (xdg_shell_view_from_view(view) == NULL) {
 | 
						if (xdg_shell_view_from_view(view) == NULL) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -189,6 +197,18 @@ static void _close(struct sway_view *view) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void close_popups_iterator(struct wlr_surface *surface,
 | 
				
			||||||
 | 
							int sx, int sy, void *data) {
 | 
				
			||||||
 | 
						struct wlr_xdg_surface *xdg_surface =
 | 
				
			||||||
 | 
							wlr_xdg_surface_from_wlr_surface(surface);
 | 
				
			||||||
 | 
						wlr_xdg_surface_send_close(xdg_surface);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void close_popups(struct sway_view *view) {
 | 
				
			||||||
 | 
						wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface,
 | 
				
			||||||
 | 
								close_popups_iterator, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void destroy(struct sway_view *view) {
 | 
					static void destroy(struct sway_view *view) {
 | 
				
			||||||
	struct sway_xdg_shell_view *xdg_shell_view =
 | 
						struct sway_xdg_shell_view *xdg_shell_view =
 | 
				
			||||||
		xdg_shell_view_from_view(view);
 | 
							xdg_shell_view_from_view(view);
 | 
				
			||||||
| 
						 | 
					@ -207,7 +227,9 @@ static const struct sway_view_impl view_impl = {
 | 
				
			||||||
	.set_fullscreen = set_fullscreen,
 | 
						.set_fullscreen = set_fullscreen,
 | 
				
			||||||
	.wants_floating = wants_floating,
 | 
						.wants_floating = wants_floating,
 | 
				
			||||||
	.for_each_surface = for_each_surface,
 | 
						.for_each_surface = for_each_surface,
 | 
				
			||||||
 | 
						.for_each_popup = for_each_popup,
 | 
				
			||||||
	.close = _close,
 | 
						.close = _close,
 | 
				
			||||||
 | 
						.close_popups = close_popups,
 | 
				
			||||||
	.destroy = destroy,
 | 
						.destroy = destroy,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view,
 | 
				
			||||||
		user_data);
 | 
							user_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void for_each_popup(struct sway_view *view,
 | 
				
			||||||
 | 
							wlr_surface_iterator_func_t iterator, void *user_data) {
 | 
				
			||||||
 | 
						if (xdg_shell_v6_view_from_view(view) == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator,
 | 
				
			||||||
 | 
							user_data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void _close(struct sway_view *view) {
 | 
					static void _close(struct sway_view *view) {
 | 
				
			||||||
	if (xdg_shell_v6_view_from_view(view) == NULL) {
 | 
						if (xdg_shell_v6_view_from_view(view) == NULL) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -185,6 +194,18 @@ static void _close(struct sway_view *view) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void close_popups_iterator(struct wlr_surface *surface,
 | 
				
			||||||
 | 
							int sx, int sy, void *data) {
 | 
				
			||||||
 | 
						struct wlr_xdg_surface_v6 *xdg_surface_v6 =
 | 
				
			||||||
 | 
							wlr_xdg_surface_v6_from_wlr_surface(surface);
 | 
				
			||||||
 | 
						wlr_xdg_surface_v6_send_close(xdg_surface_v6);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void close_popups(struct sway_view *view) {
 | 
				
			||||||
 | 
						wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6,
 | 
				
			||||||
 | 
								close_popups_iterator, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void destroy(struct sway_view *view) {
 | 
					static void destroy(struct sway_view *view) {
 | 
				
			||||||
	struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
 | 
						struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
 | 
				
			||||||
		xdg_shell_v6_view_from_view(view);
 | 
							xdg_shell_v6_view_from_view(view);
 | 
				
			||||||
| 
						 | 
					@ -203,7 +224,9 @@ static const struct sway_view_impl view_impl = {
 | 
				
			||||||
	.set_fullscreen = set_fullscreen,
 | 
						.set_fullscreen = set_fullscreen,
 | 
				
			||||||
	.wants_floating = wants_floating,
 | 
						.wants_floating = wants_floating,
 | 
				
			||||||
	.for_each_surface = for_each_surface,
 | 
						.for_each_surface = for_each_surface,
 | 
				
			||||||
 | 
						.for_each_popup = for_each_popup,
 | 
				
			||||||
	.close = _close,
 | 
						.close = _close,
 | 
				
			||||||
 | 
						.close_popups = close_popups,
 | 
				
			||||||
	.destroy = destroy,
 | 
						.destroy = destroy,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,9 +109,6 @@ static struct sway_container *container_at_coords(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_container *c;
 | 
						struct sway_container *c;
 | 
				
			||||||
	if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
 | 
					 | 
				
			||||||
		return c;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
 | 
						if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
 | 
				
			||||||
		return c;
 | 
							return c;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -349,7 +346,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
 | 
				
			||||||
				output = container_parent(c, C_OUTPUT);
 | 
									output = container_parent(c, C_OUTPUT);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (output != focus) {
 | 
								if (output != focus) {
 | 
				
			||||||
				seat_set_focus_warp(seat, c, false);
 | 
									seat_set_focus_warp(seat, c, false, true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (c->type == C_VIEW) {
 | 
							} else if (c->type == C_VIEW) {
 | 
				
			||||||
			// Focus c if the following are true:
 | 
								// Focus c if the following are true:
 | 
				
			||||||
| 
						 | 
					@ -359,13 +356,13 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
 | 
				
			||||||
			if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) &&
 | 
								if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) &&
 | 
				
			||||||
					c != prev_c &&
 | 
										c != prev_c &&
 | 
				
			||||||
					view_is_visible(c->sway_view)) {
 | 
										view_is_visible(c->sway_view)) {
 | 
				
			||||||
				seat_set_focus_warp(seat, c, false);
 | 
									seat_set_focus_warp(seat, c, false, true);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				struct sway_container *next_focus =
 | 
									struct sway_container *next_focus =
 | 
				
			||||||
					seat_get_focus_inactive(seat, &root_container);
 | 
										seat_get_focus_inactive(seat, &root_container);
 | 
				
			||||||
				if (next_focus && next_focus->type == C_VIEW &&
 | 
									if (next_focus && next_focus->type == C_VIEW &&
 | 
				
			||||||
						view_is_visible(next_focus->sway_view)) {
 | 
											view_is_visible(next_focus->sway_view)) {
 | 
				
			||||||
					seat_set_focus_warp(seat, next_focus, false);
 | 
										seat_set_focus_warp(seat, next_focus, false, true);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,7 +393,6 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
 | 
				
			||||||
		WL_SEAT_CAPABILITY_POINTER |
 | 
							WL_SEAT_CAPABILITY_POINTER |
 | 
				
			||||||
		WL_SEAT_CAPABILITY_TOUCH);
 | 
							WL_SEAT_CAPABILITY_TOUCH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seat_configure_xcursor(seat);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_insert(&input->seats, &seat->link);
 | 
						wl_list_insert(&input->seats, &seat->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,6 +437,7 @@ static void seat_apply_input_config(struct sway_seat *seat,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void seat_configure_pointer(struct sway_seat *seat,
 | 
					static void seat_configure_pointer(struct sway_seat *seat,
 | 
				
			||||||
		struct sway_seat_device *sway_device) {
 | 
							struct sway_seat_device *sway_device) {
 | 
				
			||||||
 | 
						seat_configure_xcursor(seat);
 | 
				
			||||||
	wlr_cursor_attach_input_device(seat->cursor->cursor,
 | 
						wlr_cursor_attach_input_device(seat->cursor->cursor,
 | 
				
			||||||
		sway_device->input_device->wlr_device);
 | 
							sway_device->input_device->wlr_device);
 | 
				
			||||||
	seat_apply_input_config(seat, sway_device);
 | 
						seat_apply_input_config(seat, sway_device);
 | 
				
			||||||
| 
						 | 
					@ -617,7 +617,7 @@ static int handle_urgent_timeout(void *data) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void seat_set_focus_warp(struct sway_seat *seat,
 | 
					void seat_set_focus_warp(struct sway_seat *seat,
 | 
				
			||||||
		struct sway_container *container, bool warp) {
 | 
							struct sway_container *container, bool warp, bool notify) {
 | 
				
			||||||
	if (seat->focused_layer) {
 | 
						if (seat->focused_layer) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -737,9 +737,18 @@ void seat_set_focus_warp(struct sway_seat *seat,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Close any popups on the old focus
 | 
				
			||||||
 | 
						if (last_focus && last_focus != container) {
 | 
				
			||||||
 | 
							if (last_focus->type == C_VIEW) {
 | 
				
			||||||
 | 
								view_close_popups(last_focus->sway_view);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (last_focus) {
 | 
						if (last_focus) {
 | 
				
			||||||
		if (last_workspace) {
 | 
							if (last_workspace) {
 | 
				
			||||||
			ipc_event_workspace(last_workspace, container, "focus");
 | 
								if (notify && last_workspace != new_workspace) {
 | 
				
			||||||
 | 
									 ipc_event_workspace(last_workspace, new_workspace, "focus");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (!workspace_is_visible(last_workspace)
 | 
								if (!workspace_is_visible(last_workspace)
 | 
				
			||||||
					&& workspace_is_empty(last_workspace)) {
 | 
										&& workspace_is_empty(last_workspace)) {
 | 
				
			||||||
				if (last_workspace == last_focus) {
 | 
									if (last_workspace == last_focus) {
 | 
				
			||||||
| 
						 | 
					@ -766,6 +775,10 @@ void seat_set_focus_warp(struct sway_seat *seat,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (container->type == C_VIEW) {
 | 
				
			||||||
 | 
							ipc_event_window(container, "focus");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	seat->has_focus = (container != NULL);
 | 
						seat->has_focus = (container != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	update_debug_tree();
 | 
						update_debug_tree();
 | 
				
			||||||
| 
						 | 
					@ -773,7 +786,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void seat_set_focus(struct sway_seat *seat,
 | 
					void seat_set_focus(struct sway_seat *seat,
 | 
				
			||||||
		struct sway_container *container) {
 | 
							struct sway_container *container) {
 | 
				
			||||||
	seat_set_focus_warp(seat, container, true);
 | 
						seat_set_focus_warp(seat, container, true, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void seat_set_focus_surface(struct sway_seat *seat,
 | 
					void seat_set_focus_surface(struct sway_seat *seat,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,6 +201,15 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
 | 
				
			||||||
	bool urgent = c->type == C_VIEW ?
 | 
						bool urgent = c->type == C_VIEW ?
 | 
				
			||||||
		view_is_urgent(c->sway_view) : container_has_urgent_child(c);
 | 
							view_is_urgent(c->sway_view) : container_has_urgent_child(c);
 | 
				
			||||||
	json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
 | 
						json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->type == C_VIEW) {
 | 
				
			||||||
 | 
							json_object *marks = json_object_new_array();
 | 
				
			||||||
 | 
							list_t *view_marks = c->sway_view->marks;
 | 
				
			||||||
 | 
							for (int i = 0; i < view_marks->length; ++i) {
 | 
				
			||||||
 | 
								json_object_array_add(marks, json_object_new_string(view_marks->items[i]));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							json_object_object_add(object, "marks", marks);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void focus_inactive_children_iterator(struct sway_container *c, void *data) {
 | 
					static void focus_inactive_children_iterator(struct sway_container *c, void *data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,18 @@
 | 
				
			||||||
// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
 | 
					// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
 | 
				
			||||||
#define _XOPEN_SOURCE 700
 | 
					#define _XOPEN_SOURCE 700
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef __linux__
 | 
				
			||||||
 | 
					#include <linux/input-event-codes.h>
 | 
				
			||||||
 | 
					#elif __FreeBSD__
 | 
				
			||||||
 | 
					#include <dev/evdev/input-event-codes.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <json-c/json.h>
 | 
					#include <json-c/json.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
| 
						 | 
					@ -28,6 +34,7 @@
 | 
				
			||||||
#include "sway/tree/view.h"
 | 
					#include "sway/tree/view.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ipc_socket = -1;
 | 
					static int ipc_socket = -1;
 | 
				
			||||||
static struct wl_event_source *ipc_event_source =  NULL;
 | 
					static struct wl_event_source *ipc_event_source =  NULL;
 | 
				
			||||||
| 
						 | 
					@ -291,14 +298,12 @@ void ipc_event_workspace(struct sway_container *old,
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "Sending workspace::%s event", change);
 | 
						wlr_log(WLR_DEBUG, "Sending workspace::%s event", change);
 | 
				
			||||||
	json_object *obj = json_object_new_object();
 | 
						json_object *obj = json_object_new_object();
 | 
				
			||||||
	json_object_object_add(obj, "change", json_object_new_string(change));
 | 
						json_object_object_add(obj, "change", json_object_new_string(change));
 | 
				
			||||||
	if (strcmp("focus", change) == 0) {
 | 
					 | 
				
			||||||
	if (old) {
 | 
						if (old) {
 | 
				
			||||||
		json_object_object_add(obj, "old",
 | 
							json_object_object_add(obj, "old",
 | 
				
			||||||
				ipc_json_describe_container_recursive(old));
 | 
									ipc_json_describe_container_recursive(old));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		json_object_object_add(obj, "old", NULL);
 | 
							json_object_object_add(obj, "old", NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (new) {
 | 
						if (new) {
 | 
				
			||||||
		json_object_object_add(obj, "current",
 | 
							json_object_object_add(obj, "current",
 | 
				
			||||||
| 
						 | 
					@ -353,6 +358,104 @@ void ipc_event_mode(const char *mode, bool pango) {
 | 
				
			||||||
	json_object_put(obj);
 | 
						json_object_put(obj);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_event_shutdown(const char *reason) {
 | 
				
			||||||
 | 
						if (!ipc_has_event_listeners(IPC_EVENT_SHUTDOWN)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "Sending shutdown::%s event", reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json, "change", json_object_new_string(reason));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *json_string = json_object_to_json_string(json);
 | 
				
			||||||
 | 
						ipc_send_event(json_string, IPC_EVENT_SHUTDOWN);
 | 
				
			||||||
 | 
						json_object_put(json);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_event_binding(struct sway_binding *binding) {
 | 
				
			||||||
 | 
						if (!ipc_has_event_listeners(IPC_EVENT_BINDING)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "Sending binding event");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json_binding = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "command", json_object_new_string(binding->command));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *names[10];
 | 
				
			||||||
 | 
						int len = get_modifier_names(names, binding->modifiers);
 | 
				
			||||||
 | 
						json_object *modifiers = json_object_new_array();
 | 
				
			||||||
 | 
						for (int i = 0; i < len; ++i) {
 | 
				
			||||||
 | 
							json_object_array_add(modifiers, json_object_new_string(names[i]));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "event_state_mask", modifiers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *input_codes = json_object_new_array();
 | 
				
			||||||
 | 
						int input_code = 0;
 | 
				
			||||||
 | 
						json_object *symbols = json_object_new_array();
 | 
				
			||||||
 | 
						json_object *symbol = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (binding->type == BINDING_KEYCODE) { // bindcode: populate input_codes
 | 
				
			||||||
 | 
							uint32_t keycode;
 | 
				
			||||||
 | 
							for (int i = 0; i < binding->keys->length; ++i) {
 | 
				
			||||||
 | 
								keycode = *(uint32_t *)binding->keys->items[i];
 | 
				
			||||||
 | 
								json_object_array_add(input_codes, json_object_new_int(keycode));
 | 
				
			||||||
 | 
								if (i == 0) {
 | 
				
			||||||
 | 
									input_code = keycode;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else { // bindsym/mouse: populate symbols
 | 
				
			||||||
 | 
							uint32_t keysym;
 | 
				
			||||||
 | 
							char buffer[64];
 | 
				
			||||||
 | 
							for (int i = 0; i < binding->keys->length; ++i) {
 | 
				
			||||||
 | 
								keysym = *(uint32_t *)binding->keys->items[i];
 | 
				
			||||||
 | 
								if (keysym >= BTN_LEFT && keysym <= BTN_LEFT + 8) {
 | 
				
			||||||
 | 
									snprintf(buffer, 64, "button%u", keysym - BTN_LEFT + 1);
 | 
				
			||||||
 | 
								} else if (xkb_keysym_get_name(keysym, buffer, 64) < 0) {
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								json_object *str = json_object_new_string(buffer);
 | 
				
			||||||
 | 
								if (i == 0) {
 | 
				
			||||||
 | 
									// str is owned by both symbol and symbols. Make sure
 | 
				
			||||||
 | 
									// to bump the ref count.
 | 
				
			||||||
 | 
									json_object_array_add(symbols, json_object_get(str));
 | 
				
			||||||
 | 
									symbol = str;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									json_object_array_add(symbols, str);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_codes", input_codes);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "symbols", symbols);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "symbol", symbol);
 | 
				
			||||||
 | 
						json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ?
 | 
				
			||||||
 | 
								json_object_new_string("mouse") : json_object_new_string("keyboard"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json, "change", json_object_new_string("run"));
 | 
				
			||||||
 | 
						json_object_object_add(json, "binding", json_binding);
 | 
				
			||||||
 | 
						const char *json_string = json_object_to_json_string(json);
 | 
				
			||||||
 | 
						ipc_send_event(json_string, IPC_EVENT_BINDING);
 | 
				
			||||||
 | 
						json_object_put(json);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ipc_event_tick(const char *payload) {
 | 
				
			||||||
 | 
						if (!ipc_has_event_listeners(IPC_EVENT_TICK)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "Sending tick event");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						json_object *json = json_object_new_object();
 | 
				
			||||||
 | 
						json_object_object_add(json, "first", json_object_new_boolean(false));
 | 
				
			||||||
 | 
						json_object_object_add(json, "payload", json_object_new_string(payload));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *json_string = json_object_to_json_string(json);
 | 
				
			||||||
 | 
						ipc_send_event(json_string, IPC_EVENT_TICK);
 | 
				
			||||||
 | 
						json_object_put(json);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
 | 
					int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
 | 
				
			||||||
	struct ipc_client *client = data;
 | 
						struct ipc_client *client = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -494,6 +597,13 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
		goto exit_cleanup;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case IPC_SEND_TICK:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ipc_event_tick(buf);
 | 
				
			||||||
 | 
							ipc_send_reply(client, "{\"success\": true}", 17);
 | 
				
			||||||
 | 
							goto exit_cleanup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_OUTPUTS:
 | 
						case IPC_GET_OUTPUTS:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		json_object *outputs = json_object_new_array();
 | 
							json_object *outputs = json_object_new_array();
 | 
				
			||||||
| 
						 | 
					@ -540,6 +650,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
			goto exit_cleanup;
 | 
								goto exit_cleanup;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool is_tick = false;
 | 
				
			||||||
		// parse requested event types
 | 
							// parse requested event types
 | 
				
			||||||
		for (size_t i = 0; i < json_object_array_length(request); i++) {
 | 
							for (size_t i = 0; i < json_object_array_length(request); i++) {
 | 
				
			||||||
			const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
 | 
								const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
 | 
				
			||||||
| 
						 | 
					@ -549,12 +660,15 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
				client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
 | 
				
			||||||
			} else if (strcmp(event_type, "mode") == 0) {
 | 
								} else if (strcmp(event_type, "mode") == 0) {
 | 
				
			||||||
				client->subscribed_events |= event_mask(IPC_EVENT_MODE);
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_MODE);
 | 
				
			||||||
 | 
								} else if (strcmp(event_type, "shutdown") == 0) {
 | 
				
			||||||
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN);
 | 
				
			||||||
			} else if (strcmp(event_type, "window") == 0) {
 | 
								} else if (strcmp(event_type, "window") == 0) {
 | 
				
			||||||
				client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
 | 
				
			||||||
			} else if (strcmp(event_type, "modifier") == 0) {
 | 
					 | 
				
			||||||
				client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER);
 | 
					 | 
				
			||||||
			} else if (strcmp(event_type, "binding") == 0) {
 | 
								} else if (strcmp(event_type, "binding") == 0) {
 | 
				
			||||||
				client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
 | 
				
			||||||
 | 
								} else if (strcmp(event_type, "tick") == 0) {
 | 
				
			||||||
 | 
									client->subscribed_events |= event_mask(IPC_EVENT_TICK);
 | 
				
			||||||
 | 
									is_tick = true;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				client_valid =
 | 
									client_valid =
 | 
				
			||||||
					ipc_send_reply(client, "{\"success\": false}", 18);
 | 
										ipc_send_reply(client, "{\"success\": false}", 18);
 | 
				
			||||||
| 
						 | 
					@ -566,6 +680,10 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		json_object_put(request);
 | 
							json_object_put(request);
 | 
				
			||||||
		client_valid = ipc_send_reply(client, "{\"success\": true}", 17);
 | 
							client_valid = ipc_send_reply(client, "{\"success\": true}", 17);
 | 
				
			||||||
 | 
							if (is_tick) {
 | 
				
			||||||
 | 
								client->current_command = IPC_EVENT_TICK;
 | 
				
			||||||
 | 
								ipc_send_reply(client, "{\"first\": true, \"payload\": \"\"}", 30);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		goto exit_cleanup;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ struct sway_server server;
 | 
				
			||||||
void sway_terminate(int exit_code) {
 | 
					void sway_terminate(int exit_code) {
 | 
				
			||||||
	terminate_request = true;
 | 
						terminate_request = true;
 | 
				
			||||||
	exit_value = exit_code;
 | 
						exit_value = exit_code;
 | 
				
			||||||
 | 
						ipc_event_shutdown("exit");
 | 
				
			||||||
	wl_display_terminate(server.wl_display);
 | 
						wl_display_terminate(server.wl_display);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,8 +62,10 @@ void container_create_notify(struct sway_container *container) {
 | 
				
			||||||
	// TODO send ipc event type based on the container type
 | 
						// TODO send ipc event type based on the container type
 | 
				
			||||||
	wl_signal_emit(&root_container.sway_root->events.new_container, container);
 | 
						wl_signal_emit(&root_container.sway_root->events.new_container, container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (container->type == C_VIEW || container->type == C_CONTAINER) {
 | 
						if (container->type == C_VIEW) {
 | 
				
			||||||
		ipc_event_window(container, "new");
 | 
							ipc_event_window(container, "new");
 | 
				
			||||||
 | 
						} else if (container->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
							ipc_event_workspace(NULL, container, "init");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,7 +283,7 @@ static struct sway_container *container_output_destroy(
 | 
				
			||||||
				container_remove_child(workspace);
 | 
									container_remove_child(workspace);
 | 
				
			||||||
				if (!workspace_is_empty(workspace)) {
 | 
									if (!workspace_is_empty(workspace)) {
 | 
				
			||||||
					container_add_child(new_output, workspace);
 | 
										container_add_child(new_output, workspace);
 | 
				
			||||||
					ipc_event_workspace(workspace, NULL, "move");
 | 
										ipc_event_workspace(NULL, workspace, "move");
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					container_destroy(workspace);
 | 
										container_destroy(workspace);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -319,7 +321,13 @@ static struct sway_container *container_destroy_noreaping(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_signal_emit(&con->events.destroy, con);
 | 
						wl_signal_emit(&con->events.destroy, con);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// emit IPC event
 | 
				
			||||||
 | 
						if (con->type == C_VIEW) {
 | 
				
			||||||
		ipc_event_window(con, "close");
 | 
							ipc_event_window(con, "close");
 | 
				
			||||||
 | 
						} else if (con->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
							ipc_event_workspace(NULL, con, "empty");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The below functions move their children to somewhere else.
 | 
						// The below functions move their children to somewhere else.
 | 
				
			||||||
	if (con->type == C_OUTPUT) {
 | 
						if (con->type == C_OUTPUT) {
 | 
				
			||||||
| 
						 | 
					@ -561,9 +569,14 @@ static struct sway_container *container_at_view(struct sway_container *swayc,
 | 
				
			||||||
		*sx = _sx;
 | 
							*sx = _sx;
 | 
				
			||||||
		*sy = _sy;
 | 
							*sy = _sy;
 | 
				
			||||||
		*surface = _surface;
 | 
							*surface = _surface;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		return swayc;
 | 
							return swayc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct sway_container *tiling_container_at(
 | 
				
			||||||
 | 
							struct sway_container *con, double lx, double ly,
 | 
				
			||||||
 | 
							struct wlr_surface **surface, double *sx, double *sy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * container_at for a container with layout L_TABBED.
 | 
					 * container_at for a container with layout L_TABBED.
 | 
				
			||||||
| 
						 | 
					@ -591,7 +604,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent,
 | 
				
			||||||
	// Surfaces
 | 
						// Surfaces
 | 
				
			||||||
	struct sway_container *current = seat_get_active_child(seat, parent);
 | 
						struct sway_container *current = seat_get_active_child(seat, parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return container_at(current, lx, ly, surface, sx, sy);
 | 
						return tiling_container_at(current, lx, ly, surface, sx, sy);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -616,7 +629,7 @@ static struct sway_container *container_at_stacked(
 | 
				
			||||||
	// Surfaces
 | 
						// Surfaces
 | 
				
			||||||
	struct sway_container *current = seat_get_active_child(seat, parent);
 | 
						struct sway_container *current = seat_get_active_child(seat, parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return container_at(current, lx, ly, surface, sx, sy);
 | 
						return tiling_container_at(current, lx, ly, surface, sx, sy);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -634,45 +647,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
 | 
				
			||||||
			.height = child->height,
 | 
								.height = child->height,
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		if (wlr_box_contains_point(&box, lx, ly)) {
 | 
							if (wlr_box_contains_point(&box, lx, ly)) {
 | 
				
			||||||
			return container_at(child, lx, ly, surface, sx, sy);
 | 
								return tiling_container_at(child, lx, ly, surface, sx, sy);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_container *container_at(struct sway_container *parent,
 | 
					static struct sway_container *floating_container_at(double lx, double ly,
 | 
				
			||||||
		double lx, double ly,
 | 
					 | 
				
			||||||
		struct wlr_surface **surface, double *sx, double *sy) {
 | 
					 | 
				
			||||||
	if (!sway_assert(parent->type >= C_WORKSPACE,
 | 
					 | 
				
			||||||
				"Expected workspace or deeper")) {
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (parent->type == C_VIEW) {
 | 
					 | 
				
			||||||
		return container_at_view(parent, lx, ly, surface, sx, sy);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!parent->children->length) {
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (parent->layout) {
 | 
					 | 
				
			||||||
	case L_HORIZ:
 | 
					 | 
				
			||||||
	case L_VERT:
 | 
					 | 
				
			||||||
		return container_at_linear(parent, lx, ly, surface, sx, sy);
 | 
					 | 
				
			||||||
	case L_TABBED:
 | 
					 | 
				
			||||||
		return container_at_tabbed(parent, lx, ly, surface, sx, sy);
 | 
					 | 
				
			||||||
	case L_STACKED:
 | 
					 | 
				
			||||||
		return container_at_stacked(parent, lx, ly, surface, sx, sy);
 | 
					 | 
				
			||||||
	case L_FLOATING:
 | 
					 | 
				
			||||||
		sway_assert(false, "Didn't expect to see floating here");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	case L_NONE:
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sway_container *floating_container_at(double lx, double ly,
 | 
					 | 
				
			||||||
		struct wlr_surface **surface, double *sx, double *sy) {
 | 
							struct wlr_surface **surface, double *sx, double *sy) {
 | 
				
			||||||
	for (int i = 0; i < root_container.children->length; ++i) {
 | 
						for (int i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
		struct sway_container *output = root_container.children->items[i];
 | 
							struct sway_container *output = root_container.children->items[i];
 | 
				
			||||||
| 
						 | 
					@ -694,7 +675,8 @@ struct sway_container *floating_container_at(double lx, double ly,
 | 
				
			||||||
					.height = floater->height,
 | 
										.height = floater->height,
 | 
				
			||||||
				};
 | 
									};
 | 
				
			||||||
				if (wlr_box_contains_point(&box, lx, ly)) {
 | 
									if (wlr_box_contains_point(&box, lx, ly)) {
 | 
				
			||||||
					return container_at(floater, lx, ly, surface, sx, sy);
 | 
										return tiling_container_at(floater, lx, ly,
 | 
				
			||||||
 | 
												surface, sx, sy);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -702,6 +684,90 @@ struct sway_container *floating_container_at(double lx, double ly,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct sway_container *tiling_container_at(
 | 
				
			||||||
 | 
							struct sway_container *con, double lx, double ly,
 | 
				
			||||||
 | 
							struct wlr_surface **surface, double *sx, double *sy) {
 | 
				
			||||||
 | 
						if (con->type == C_VIEW) {
 | 
				
			||||||
 | 
							return container_at_view(con, lx, ly, surface, sx, sy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!con->children->length) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (con->layout) {
 | 
				
			||||||
 | 
						case L_HORIZ:
 | 
				
			||||||
 | 
						case L_VERT:
 | 
				
			||||||
 | 
							return container_at_linear(con, lx, ly, surface, sx, sy);
 | 
				
			||||||
 | 
						case L_TABBED:
 | 
				
			||||||
 | 
							return container_at_tabbed(con, lx, ly, surface, sx, sy);
 | 
				
			||||||
 | 
						case L_STACKED:
 | 
				
			||||||
 | 
							return container_at_stacked(con, lx, ly, surface, sx, sy);
 | 
				
			||||||
 | 
						case L_FLOATING:
 | 
				
			||||||
 | 
							sway_assert(false, "Didn't expect to see floating here");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						case L_NONE:
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool surface_is_popup(struct wlr_surface *surface) {
 | 
				
			||||||
 | 
						if (wlr_surface_is_xdg_surface(surface)) {
 | 
				
			||||||
 | 
							struct wlr_xdg_surface *xdg_surface =
 | 
				
			||||||
 | 
								wlr_xdg_surface_from_wlr_surface(surface);
 | 
				
			||||||
 | 
							while (xdg_surface) {
 | 
				
			||||||
 | 
								if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								xdg_surface = xdg_surface->toplevel->parent;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wlr_surface_is_xdg_surface_v6(surface)) {
 | 
				
			||||||
 | 
							struct wlr_xdg_surface_v6 *xdg_surface_v6 =
 | 
				
			||||||
 | 
								wlr_xdg_surface_v6_from_wlr_surface(surface);
 | 
				
			||||||
 | 
							while (xdg_surface_v6) {
 | 
				
			||||||
 | 
								if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								xdg_surface_v6 = xdg_surface_v6->toplevel->parent;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sway_container *container_at(struct sway_container *workspace,
 | 
				
			||||||
 | 
							double lx, double ly,
 | 
				
			||||||
 | 
							struct wlr_surface **surface, double *sx, double *sy) {
 | 
				
			||||||
 | 
						if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct sway_container *c;
 | 
				
			||||||
 | 
						// Focused view's popups
 | 
				
			||||||
 | 
						struct sway_seat *seat = input_manager_current_seat(input_manager);
 | 
				
			||||||
 | 
						struct sway_container *focus =
 | 
				
			||||||
 | 
							seat_get_focus_inactive(seat, &root_container);
 | 
				
			||||||
 | 
						if (focus && focus->type == C_VIEW) {
 | 
				
			||||||
 | 
							container_at_view(focus, lx, ly, surface, sx, sy);
 | 
				
			||||||
 | 
							if (*surface && surface_is_popup(*surface)) {
 | 
				
			||||||
 | 
								return focus;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*surface = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Floating
 | 
				
			||||||
 | 
						if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
 | 
				
			||||||
 | 
							return c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Tiling
 | 
				
			||||||
 | 
						if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
 | 
				
			||||||
 | 
							return c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void container_for_each_descendant_dfs(struct sway_container *container,
 | 
					void container_for_each_descendant_dfs(struct sway_container *container,
 | 
				
			||||||
		void (*f)(struct sway_container *container, void *data),
 | 
							void (*f)(struct sway_container *container, void *data),
 | 
				
			||||||
		void *data) {
 | 
							void *data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,7 +217,9 @@ void container_move_to(struct sway_container *container,
 | 
				
			||||||
		container_sort_workspaces(new_parent);
 | 
							container_sort_workspaces(new_parent);
 | 
				
			||||||
		seat_set_focus(seat, new_parent);
 | 
							seat_set_focus(seat, new_parent);
 | 
				
			||||||
		workspace_output_raise_priority(container, old_parent, new_parent);
 | 
							workspace_output_raise_priority(container, old_parent, new_parent);
 | 
				
			||||||
		ipc_event_workspace(container, NULL, "move");
 | 
							ipc_event_workspace(NULL, container, "move");
 | 
				
			||||||
 | 
						} else if (container->type == C_VIEW) {
 | 
				
			||||||
 | 
							ipc_event_window(container, "move");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	container_notify_subtree_changed(old_parent);
 | 
						container_notify_subtree_changed(old_parent);
 | 
				
			||||||
	container_notify_subtree_changed(new_parent);
 | 
						container_notify_subtree_changed(new_parent);
 | 
				
			||||||
| 
						 | 
					@ -578,6 +580,10 @@ void container_move(struct sway_container *container,
 | 
				
			||||||
	container_notify_subtree_changed(old_parent);
 | 
						container_notify_subtree_changed(old_parent);
 | 
				
			||||||
	container_notify_subtree_changed(container->parent);
 | 
						container_notify_subtree_changed(container->parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (container->type == C_VIEW) {
 | 
				
			||||||
 | 
							ipc_event_window(container, "move");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (old_parent) {
 | 
						if (old_parent) {
 | 
				
			||||||
		seat_set_focus(config->handler_context.seat, old_parent);
 | 
							seat_set_focus(config->handler_context.seat, old_parent);
 | 
				
			||||||
		seat_set_focus(config->handler_context.seat, container);
 | 
							seat_set_focus(config->handler_context.seat, container);
 | 
				
			||||||
| 
						 | 
					@ -592,7 +598,7 @@ void container_move(struct sway_container *container,
 | 
				
			||||||
		next_ws = container_parent(next_ws, C_WORKSPACE);
 | 
							next_ws = container_parent(next_ws, C_WORKSPACE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (last_ws && next_ws && last_ws != next_ws) {
 | 
						if (last_ws && next_ws && last_ws != next_ws) {
 | 
				
			||||||
		ipc_event_workspace(last_ws, container, "focus");
 | 
							ipc_event_workspace(last_ws, next_ws, "focus");
 | 
				
			||||||
		workspace_detect_urgent(last_ws);
 | 
							workspace_detect_urgent(last_ws);
 | 
				
			||||||
		workspace_detect_urgent(next_ws);
 | 
							workspace_detect_urgent(next_ws);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -995,13 +1001,13 @@ static void swap_focus(struct sway_container *con1,
 | 
				
			||||||
		if (focus == con1 && (con2->parent->layout == L_TABBED
 | 
							if (focus == con1 && (con2->parent->layout == L_TABBED
 | 
				
			||||||
					|| con2->parent->layout == L_STACKED)) {
 | 
										|| con2->parent->layout == L_STACKED)) {
 | 
				
			||||||
			if (workspace_is_visible(ws2)) {
 | 
								if (workspace_is_visible(ws2)) {
 | 
				
			||||||
				seat_set_focus_warp(seat, con2, false);
 | 
									seat_set_focus_warp(seat, con2, false, true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
 | 
								seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
 | 
				
			||||||
		} else if (focus == con2 && (con1->parent->layout == L_TABBED
 | 
							} else if (focus == con2 && (con1->parent->layout == L_TABBED
 | 
				
			||||||
					|| con1->parent->layout == L_STACKED)) {
 | 
										|| con1->parent->layout == L_STACKED)) {
 | 
				
			||||||
			if (workspace_is_visible(ws1)) {
 | 
								if (workspace_is_visible(ws1)) {
 | 
				
			||||||
				seat_set_focus_warp(seat, con1, false);
 | 
									seat_set_focus_warp(seat, con1, false, true);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
 | 
								seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
 | 
				
			||||||
		} else if (ws1 != ws2) {
 | 
							} else if (ws1 != ws2) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ static void restore_workspaces(struct sway_container *output) {
 | 
				
			||||||
			if (highest == output) {
 | 
								if (highest == output) {
 | 
				
			||||||
				container_remove_child(ws);
 | 
									container_remove_child(ws);
 | 
				
			||||||
				container_add_child(output, ws);
 | 
									container_add_child(output, ws);
 | 
				
			||||||
				ipc_event_workspace(ws, NULL, "move");
 | 
									ipc_event_workspace(NULL, ws, "move");
 | 
				
			||||||
				j--;
 | 
									j--;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -303,6 +303,12 @@ void view_close(struct sway_view *view) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_close_popups(struct sway_view *view) {
 | 
				
			||||||
 | 
						if (view->impl->close_popups) {
 | 
				
			||||||
 | 
							view->impl->close_popups(view);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_damage_from(struct sway_view *view) {
 | 
					void view_damage_from(struct sway_view *view) {
 | 
				
			||||||
	for (int i = 0; i < root_container.children->length; ++i) {
 | 
						for (int i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
		struct sway_container *cont = root_container.children->items[i];
 | 
							struct sway_container *cont = root_container.children->items[i];
 | 
				
			||||||
| 
						 | 
					@ -333,6 +339,16 @@ void view_for_each_surface(struct sway_view *view,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_for_each_popup(struct sway_view *view,
 | 
				
			||||||
 | 
							wlr_surface_iterator_func_t iterator, void *user_data) {
 | 
				
			||||||
 | 
						if (!view->surface) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (view->impl->for_each_popup) {
 | 
				
			||||||
 | 
							view->impl->for_each_popup(view, iterator, user_data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void view_subsurface_create(struct sway_view *view,
 | 
					static void view_subsurface_create(struct sway_view *view,
 | 
				
			||||||
	struct wlr_subsurface *subsurface);
 | 
						struct wlr_subsurface *subsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -865,6 +881,8 @@ void view_update_title(struct sway_view *view, bool force) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update title after the global font height is updated
 | 
						// Update title after the global font height is updated
 | 
				
			||||||
	container_update_title_textures(view->swayc);
 | 
						container_update_title_textures(view->swayc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipc_event_window(view->swayc, "title");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_by_mark_iterator(struct sway_container *con,
 | 
					static bool find_by_mark_iterator(struct sway_container *con,
 | 
				
			||||||
| 
						 | 
					@ -887,6 +905,7 @@ bool view_find_and_unmark(char *mark) {
 | 
				
			||||||
			free(view_mark);
 | 
								free(view_mark);
 | 
				
			||||||
			list_del(view->marks, i);
 | 
								list_del(view->marks, i);
 | 
				
			||||||
			view_update_marks_textures(view);
 | 
								view_update_marks_textures(view);
 | 
				
			||||||
 | 
								ipc_event_window(container, "mark");
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -894,11 +913,10 @@ bool view_find_and_unmark(char *mark) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_clear_marks(struct sway_view *view) {
 | 
					void view_clear_marks(struct sway_view *view) {
 | 
				
			||||||
	for (int i = 0; i < view->marks->length; ++i) {
 | 
						while (view->marks->length) {
 | 
				
			||||||
		free(view->marks->items[i]);
 | 
							list_del(view->marks, 0);
 | 
				
			||||||
 | 
							ipc_event_window(view->swayc, "mark");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list_free(view->marks);
 | 
					 | 
				
			||||||
	view->marks = create_list();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool view_has_mark(struct sway_view *view, char *mark) {
 | 
					bool view_has_mark(struct sway_view *view, char *mark) {
 | 
				
			||||||
| 
						 | 
					@ -911,6 +929,11 @@ bool view_has_mark(struct sway_view *view, char *mark) {
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_add_mark(struct sway_view *view, char *mark) {
 | 
				
			||||||
 | 
						list_add(view->marks, strdup(mark));
 | 
				
			||||||
 | 
						ipc_event_window(view->swayc, "mark");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_marks_texture(struct sway_view *view,
 | 
					static void update_marks_texture(struct sway_view *view,
 | 
				
			||||||
		struct wlr_texture **texture, struct border_colors *class) {
 | 
							struct wlr_texture **texture, struct border_colors *class) {
 | 
				
			||||||
	struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
 | 
						struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,12 +250,16 @@ static void pretty_print(int type, json_object *resp) {
 | 
				
			||||||
	if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES &&
 | 
						if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES &&
 | 
				
			||||||
			type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS &&
 | 
								type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS &&
 | 
				
			||||||
			type != IPC_GET_VERSION && type != IPC_GET_SEATS &&
 | 
								type != IPC_GET_VERSION && type != IPC_GET_SEATS &&
 | 
				
			||||||
			type != IPC_GET_CONFIG) {
 | 
								type != IPC_GET_CONFIG && type != IPC_SEND_TICK) {
 | 
				
			||||||
		printf("%s\n", json_object_to_json_string_ext(resp,
 | 
							printf("%s\n", json_object_to_json_string_ext(resp,
 | 
				
			||||||
			JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED));
 | 
								JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED));
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (type == IPC_SEND_TICK) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (type == IPC_GET_VERSION) {
 | 
						if (type == IPC_GET_VERSION) {
 | 
				
			||||||
		pretty_print_version(resp);
 | 
							pretty_print_version(resp);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -384,6 +388,8 @@ int main(int argc, char **argv) {
 | 
				
			||||||
		type = IPC_GET_BINDING_MODES;
 | 
							type = IPC_GET_BINDING_MODES;
 | 
				
			||||||
	} else if (strcasecmp(cmdtype, "get_config") == 0) {
 | 
						} else if (strcasecmp(cmdtype, "get_config") == 0) {
 | 
				
			||||||
		type = IPC_GET_CONFIG;
 | 
							type = IPC_GET_CONFIG;
 | 
				
			||||||
 | 
						} else if (strcasecmp(cmdtype, "send_tick") == 0) {
 | 
				
			||||||
 | 
							type = IPC_SEND_TICK;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		sway_abort("Unknown message type %s", cmdtype);
 | 
							sway_abort("Unknown message type %s", cmdtype);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,3 +64,6 @@ _swaymsg_ [options...] [message]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*get\_config*
 | 
					*get\_config*
 | 
				
			||||||
	Gets a JSON-encoded copy of the current configuration.
 | 
						Gets a JSON-encoded copy of the current configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*send\_tick*
 | 
				
			||||||
 | 
						Sends a tick event to all subscribed clients.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue