mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #2666 from emersion/swaybar-hotplug
swaybar: handle hotplugging
This commit is contained in:
		
						commit
						d2a0a3cc0a
					
				
					 6 changed files with 82 additions and 68 deletions
				
			
		| 
						 | 
					@ -512,9 +512,7 @@ void free_sway_binding(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(void);
 | 
				
			||||||
 | 
					 | 
				
			||||||
void invoke_swaybar(struct bar_config *bar);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void terminate_swaybg(pid_t pid);
 | 
					void terminate_swaybg(pid_t pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@ cleanup:
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void invoke_swaybar(struct bar_config *bar) {
 | 
					static void invoke_swaybar(struct bar_config *bar) {
 | 
				
			||||||
	// Pipe to communicate errors
 | 
						// Pipe to communicate errors
 | 
				
			||||||
	int filedes[2];
 | 
						int filedes[2];
 | 
				
			||||||
	if (pipe(filedes) == -1) {
 | 
						if (pipe(filedes) == -1) {
 | 
				
			||||||
| 
						 | 
					@ -219,22 +219,9 @@ void invoke_swaybar(struct bar_config *bar) {
 | 
				
			||||||
	close(filedes[1]);
 | 
						close(filedes[1]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void load_swaybars() {
 | 
					void load_swaybars(void) {
 | 
				
			||||||
	for (int i = 0; i < config->bars->length; ++i) {
 | 
						for (int i = 0; i < config->bars->length; ++i) {
 | 
				
			||||||
		struct bar_config *bar = config->bars->items[i];
 | 
							struct bar_config *bar = config->bars->items[i];
 | 
				
			||||||
		bool apply = false;
 | 
					 | 
				
			||||||
		if (bar->outputs) {
 | 
					 | 
				
			||||||
			for (int j = 0; j < bar->outputs->length; ++j) {
 | 
					 | 
				
			||||||
				char *o = bar->outputs->items[j];
 | 
					 | 
				
			||||||
				if (!strcmp(o, "*") || output_by_name(o)) {
 | 
					 | 
				
			||||||
					apply = true;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			apply = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (apply) {
 | 
					 | 
				
			||||||
		if (bar->pid != 0) {
 | 
							if (bar->pid != 0) {
 | 
				
			||||||
			terminate_swaybar(bar->pid);
 | 
								terminate_swaybar(bar->pid);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -242,4 +229,3 @@ void load_swaybars() {
 | 
				
			||||||
		invoke_swaybar(bar);
 | 
							invoke_swaybar(bar);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,6 +424,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config->active = true;
 | 
						config->active = true;
 | 
				
			||||||
 | 
						load_swaybars();
 | 
				
			||||||
	// Execute commands until there are none left
 | 
						// Execute commands until there are none left
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "Running deferred commands");
 | 
						wlr_log(WLR_DEBUG, "Running deferred commands");
 | 
				
			||||||
	while (config->cmd_queue->length) {
 | 
						while (config->cmd_queue->length) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,8 +109,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_signal_emit(&root->events.new_node, &output->node);
 | 
						wl_signal_emit(&root->events.new_node, &output->node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	load_swaybars();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	arrange_layers(output);
 | 
						arrange_layers(output);
 | 
				
			||||||
	arrange_root();
 | 
						arrange_root();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										106
									
								
								swaybar/bar.c
									
										
									
									
									
								
							
							
						
						
									
										106
									
								
								swaybar/bar.c
									
										
									
									
									
								
							| 
						 | 
					@ -48,8 +48,13 @@ static void swaybar_output_free(struct swaybar_output *output) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wlr_log(WLR_DEBUG, "Removing output %s", output->name);
 | 
						wlr_log(WLR_DEBUG, "Removing output %s", output->name);
 | 
				
			||||||
 | 
						if (output->layer_surface != NULL) {
 | 
				
			||||||
		zwlr_layer_surface_v1_destroy(output->layer_surface);
 | 
							zwlr_layer_surface_v1_destroy(output->layer_surface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (output->surface != NULL) {
 | 
				
			||||||
		wl_surface_destroy(output->surface);
 | 
							wl_surface_destroy(output->surface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						zxdg_output_v1_destroy(output->xdg_output);
 | 
				
			||||||
	wl_output_destroy(output->output);
 | 
						wl_output_destroy(output->output);
 | 
				
			||||||
	destroy_buffer(&output->buffers[0]);
 | 
						destroy_buffer(&output->buffers[0]);
 | 
				
			||||||
	destroy_buffer(&output->buffers[1]);
 | 
						destroy_buffer(&output->buffers[1]);
 | 
				
			||||||
| 
						 | 
					@ -283,6 +288,37 @@ const struct wl_seat_listener seat_listener = {
 | 
				
			||||||
	.name = seat_handle_name,
 | 
						.name = seat_handle_name,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void add_layer_surface(struct swaybar_output *output) {
 | 
				
			||||||
 | 
						if (output->surface != NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct swaybar *bar = output->bar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output->surface = wl_compositor_create_surface(bar->compositor);
 | 
				
			||||||
 | 
						assert(output->surface);
 | 
				
			||||||
 | 
						output->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
 | 
				
			||||||
 | 
								bar->layer_shell, output->surface, output->output,
 | 
				
			||||||
 | 
								ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel");
 | 
				
			||||||
 | 
						assert(output->layer_surface);
 | 
				
			||||||
 | 
						zwlr_layer_surface_v1_add_listener(output->layer_surface,
 | 
				
			||||||
 | 
								&layer_surface_listener, output);
 | 
				
			||||||
 | 
						zwlr_layer_surface_v1_set_anchor(output->layer_surface,
 | 
				
			||||||
 | 
								bar->config->position);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool bar_uses_output(struct swaybar *bar, const char *name) {
 | 
				
			||||||
 | 
						if (bar->config->all_outputs) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct config_output *coutput;
 | 
				
			||||||
 | 
						wl_list_for_each(coutput, &bar->config->outputs, link) {
 | 
				
			||||||
 | 
							if (strcmp(coutput->name, name) == 0) {
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void output_geometry(void *data, struct wl_output *output, int32_t x,
 | 
					static void output_geometry(void *data, struct wl_output *output, int32_t x,
 | 
				
			||||||
		int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel,
 | 
							int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel,
 | 
				
			||||||
		const char *make, const char *model, int32_t transform) {
 | 
							const char *make, const char *model, int32_t transform) {
 | 
				
			||||||
| 
						 | 
					@ -326,7 +362,22 @@ static void xdg_output_handle_logical_size(void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xdg_output_handle_done(void *data,
 | 
					static void xdg_output_handle_done(void *data,
 | 
				
			||||||
		struct zxdg_output_v1 *xdg_output) {
 | 
							struct zxdg_output_v1 *xdg_output) {
 | 
				
			||||||
	// Who cares
 | 
						struct swaybar_output *output = data;
 | 
				
			||||||
 | 
						struct swaybar *bar = output->bar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(output->name != NULL);
 | 
				
			||||||
 | 
						if (!bar_uses_output(bar, output->name)) {
 | 
				
			||||||
 | 
							swaybar_output_free(output);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wl_list_empty(&output->link)) {
 | 
				
			||||||
 | 
							wl_list_remove(&output->link);
 | 
				
			||||||
 | 
							wl_list_insert(&bar->outputs, &output->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							add_layer_surface(output);
 | 
				
			||||||
 | 
							render_frame(bar, output);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xdg_output_handle_name(void *data,
 | 
					static void xdg_output_handle_name(void *data,
 | 
				
			||||||
| 
						 | 
					@ -349,17 +400,15 @@ struct zxdg_output_v1_listener xdg_output_listener = {
 | 
				
			||||||
	.description = xdg_output_handle_description,
 | 
						.description = xdg_output_handle_description,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool bar_uses_output(struct swaybar *bar, const char *name) {
 | 
					static void add_xdg_output(struct swaybar_output *output) {
 | 
				
			||||||
	if (bar->config->all_outputs) {
 | 
						if (output->xdg_output != NULL) {
 | 
				
			||||||
		return true;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct config_output *coutput;
 | 
						assert(output->bar->xdg_output_manager != NULL);
 | 
				
			||||||
	wl_list_for_each(coutput, &bar->config->outputs, link) {
 | 
						output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
 | 
				
			||||||
		if (strcmp(coutput->name, name) == 0) {
 | 
							output->bar->xdg_output_manager, output->output);
 | 
				
			||||||
			return true;
 | 
						zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener,
 | 
				
			||||||
		}
 | 
							output);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_global(void *data, struct wl_registry *registry,
 | 
					static void handle_global(void *data, struct wl_registry *registry,
 | 
				
			||||||
| 
						 | 
					@ -386,7 +435,10 @@ static void handle_global(void *data, struct wl_registry *registry,
 | 
				
			||||||
		output->wl_name = name;
 | 
							output->wl_name = name;
 | 
				
			||||||
		wl_list_init(&output->workspaces);
 | 
							wl_list_init(&output->workspaces);
 | 
				
			||||||
		wl_list_init(&output->hotspots);
 | 
							wl_list_init(&output->hotspots);
 | 
				
			||||||
		wl_list_insert(&bar->outputs, &output->link);
 | 
							wl_list_init(&output->link);
 | 
				
			||||||
 | 
							if (bar->xdg_output_manager != NULL) {
 | 
				
			||||||
 | 
								add_xdg_output(output);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
 | 
						} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
 | 
				
			||||||
		bar->layer_shell = wl_registry_bind(
 | 
							bar->layer_shell = wl_registry_bind(
 | 
				
			||||||
				registry, name, &zwlr_layer_shell_v1_interface, 1);
 | 
									registry, name, &zwlr_layer_shell_v1_interface, 1);
 | 
				
			||||||
| 
						 | 
					@ -416,9 +468,11 @@ static const struct wl_registry_listener registry_listener = {
 | 
				
			||||||
static void render_all_frames(struct swaybar *bar) {
 | 
					static void render_all_frames(struct swaybar *bar) {
 | 
				
			||||||
	struct swaybar_output *output;
 | 
						struct swaybar_output *output;
 | 
				
			||||||
	wl_list_for_each(output, &bar->outputs, link) {
 | 
						wl_list_for_each(output, &bar->outputs, link) {
 | 
				
			||||||
 | 
							if (output->surface != NULL) {
 | 
				
			||||||
			render_frame(bar, output);
 | 
								render_frame(bar, output);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void bar_setup(struct swaybar *bar,
 | 
					void bar_setup(struct swaybar *bar,
 | 
				
			||||||
		const char *socket_path, const char *bar_id) {
 | 
							const char *socket_path, const char *bar_id) {
 | 
				
			||||||
| 
						 | 
					@ -443,23 +497,10 @@ void bar_setup(struct swaybar *bar,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct swaybar_output *output;
 | 
						struct swaybar_output *output;
 | 
				
			||||||
	wl_list_for_each(output, &bar->outputs, link) {
 | 
						wl_list_for_each(output, &bar->outputs, link) {
 | 
				
			||||||
		output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
 | 
							add_xdg_output(output);
 | 
				
			||||||
			bar->xdg_output_manager, output->output);
 | 
					 | 
				
			||||||
		zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener,
 | 
					 | 
				
			||||||
			output);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wl_display_roundtrip(bar->display);
 | 
						wl_display_roundtrip(bar->display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct swaybar_output *output_tmp;
 | 
					 | 
				
			||||||
	wl_list_for_each_safe(output, output_tmp, &bar->outputs, link) {
 | 
					 | 
				
			||||||
		if (!bar_uses_output(bar, output->name)) {
 | 
					 | 
				
			||||||
			zxdg_output_v1_destroy(output->xdg_output);
 | 
					 | 
				
			||||||
			wl_output_destroy(output->output);
 | 
					 | 
				
			||||||
			wl_list_remove(&output->link);
 | 
					 | 
				
			||||||
			free(output);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct swaybar_pointer *pointer = &bar->pointer;
 | 
						struct swaybar_pointer *pointer = &bar->pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int max_scale = 1;
 | 
						int max_scale = 1;
 | 
				
			||||||
| 
						 | 
					@ -479,18 +520,6 @@ void bar_setup(struct swaybar *bar,
 | 
				
			||||||
	pointer->cursor_surface = wl_compositor_create_surface(bar->compositor);
 | 
						pointer->cursor_surface = wl_compositor_create_surface(bar->compositor);
 | 
				
			||||||
	assert(pointer->cursor_surface);
 | 
						assert(pointer->cursor_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_for_each(output, &bar->outputs, link) {
 | 
					 | 
				
			||||||
		output->surface = wl_compositor_create_surface(bar->compositor);
 | 
					 | 
				
			||||||
		assert(output->surface);
 | 
					 | 
				
			||||||
		output->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
 | 
					 | 
				
			||||||
				bar->layer_shell, output->surface, output->output,
 | 
					 | 
				
			||||||
				ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel");
 | 
					 | 
				
			||||||
		assert(output->layer_surface);
 | 
					 | 
				
			||||||
		zwlr_layer_surface_v1_add_listener(output->layer_surface,
 | 
					 | 
				
			||||||
				&layer_surface_listener, output);
 | 
					 | 
				
			||||||
		zwlr_layer_surface_v1_set_anchor(output->layer_surface,
 | 
					 | 
				
			||||||
				bar->config->position);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ipc_get_workspaces(bar);
 | 
						ipc_get_workspaces(bar);
 | 
				
			||||||
	render_all_frames(bar);
 | 
						render_all_frames(bar);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -529,6 +558,7 @@ void bar_run(struct swaybar *bar) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	while (1) {
 | 
						while (1) {
 | 
				
			||||||
		event_loop_poll();
 | 
							event_loop_poll();
 | 
				
			||||||
 | 
							wl_display_flush(bar->display);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
#define _POSIX_C_SOURCE 200809L
 | 
					#define _POSIX_C_SOURCE 200809L
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
| 
						 | 
					@ -480,6 +481,8 @@ static uint32_t render_to_cairo(cairo_t *cairo,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void render_frame(struct swaybar *bar, struct swaybar_output *output) {
 | 
					void render_frame(struct swaybar *bar, struct swaybar_output *output) {
 | 
				
			||||||
 | 
						assert(output->surface != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct swaybar_hotspot *hotspot, *tmp;
 | 
						struct swaybar_hotspot *hotspot, *tmp;
 | 
				
			||||||
	wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) {
 | 
						wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) {
 | 
				
			||||||
		if (hotspot->destroy) {
 | 
							if (hotspot->destroy) {
 | 
				
			||||||
| 
						 | 
					@ -507,7 +510,6 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) {
 | 
				
			||||||
		// TODO: this could infinite loop if the compositor assigns us a
 | 
							// TODO: this could infinite loop if the compositor assigns us a
 | 
				
			||||||
		// different height than what we asked for
 | 
							// different height than what we asked for
 | 
				
			||||||
		wl_surface_commit(output->surface);
 | 
							wl_surface_commit(output->surface);
 | 
				
			||||||
		wl_display_roundtrip(bar->display);
 | 
					 | 
				
			||||||
	} else if (height > 0) {
 | 
						} else if (height > 0) {
 | 
				
			||||||
		// Replay recording into shm and send it off
 | 
							// Replay recording into shm and send it off
 | 
				
			||||||
		output->current_buffer = get_next_buffer(bar->shm,
 | 
							output->current_buffer = get_next_buffer(bar->shm,
 | 
				
			||||||
| 
						 | 
					@ -533,7 +535,6 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) {
 | 
				
			||||||
		wl_surface_damage(output->surface, 0, 0,
 | 
							wl_surface_damage(output->surface, 0, 0,
 | 
				
			||||||
				output->width, output->height);
 | 
									output->width, output->height);
 | 
				
			||||||
		wl_surface_commit(output->surface);
 | 
							wl_surface_commit(output->surface);
 | 
				
			||||||
		wl_display_roundtrip(bar->display);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cairo_surface_destroy(recorder);
 | 
						cairo_surface_destroy(recorder);
 | 
				
			||||||
	cairo_destroy(cairo);
 | 
						cairo_destroy(cairo);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue