aboutsummaryrefslogtreecommitdiffstats
path: root/swaybg
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2019-01-17 11:13:10 +0100
committerLibravatar emersion <contact@emersion.fr>2019-01-17 11:13:10 +0100
commit000b31398510a44773ba5a248108c3e2ffa08ebf (patch)
tree8c87fd8fa3490162a7286bd55fd763b59160fcf3 /swaybg
parentFixes for small existing bugs. (diff)
downloadsway-000b31398510a44773ba5a248108c3e2ffa08ebf.tar.gz
sway-000b31398510a44773ba5a248108c3e2ffa08ebf.tar.zst
sway-000b31398510a44773ba5a248108c3e2ffa08ebf.zip
swaybg: use output names instead of output indexes
Diffstat (limited to 'swaybg')
-rw-r--r--swaybg/main.c141
1 files changed, 108 insertions, 33 deletions
diff --git a/swaybg/main.c b/swaybg/main.c
index 45b7a913..e3ef3d7c 100644
--- a/swaybg/main.c
+++ b/swaybg/main.c
@@ -8,13 +8,16 @@
8#include <wayland-client.h> 8#include <wayland-client.h>
9#include <wlr/util/log.h> 9#include <wlr/util/log.h>
10#include "background-image.h" 10#include "background-image.h"
11#include "pool-buffer.h"
12#include "cairo.h" 11#include "cairo.h"
12#include "pool-buffer.h"
13#include "util.h" 13#include "util.h"
14#include "wlr-layer-shell-unstable-v1-client-protocol.h" 14#include "wlr-layer-shell-unstable-v1-client-protocol.h"
15#include "xdg-output-unstable-v1-client-protocol.h"
16
17struct swaybg_state;
15 18
16struct swaybg_args { 19struct swaybg_args {
17 int output_idx; 20 const char *output;
18 const char *path; 21 const char *path;
19 enum background_mode mode; 22 enum background_mode mode;
20 const char *fallback; 23 const char *fallback;
@@ -25,23 +28,33 @@ struct swaybg_context {
25 cairo_surface_t *image; 28 cairo_surface_t *image;
26}; 29};
27 30
31struct swaybg_output {
32 struct wl_output *wl_output;
33 struct zxdg_output_v1 *xdg_output;
34 struct swaybg_state *state;
35 struct wl_list link;
36
37 int32_t scale;
38};
39
28struct swaybg_state { 40struct swaybg_state {
29 const struct swaybg_args *args; 41 const struct swaybg_args *args;
30 struct swaybg_context context; 42 struct swaybg_context context;
31 43
32 struct wl_display *display; 44 struct wl_display *display;
33 struct wl_compositor *compositor; 45 struct wl_compositor *compositor;
34 struct zwlr_layer_shell_v1 *layer_shell;
35 struct wl_shm *shm; 46 struct wl_shm *shm;
47 struct wl_list outputs;
48 struct zwlr_layer_shell_v1 *layer_shell;
49 struct zxdg_output_manager_v1 *xdg_output_manager;
36 50
37 struct wl_output *output; 51 struct swaybg_output *output;
38 struct wl_surface *surface; 52 struct wl_surface *surface;
39 struct wl_region *input_region; 53 struct wl_region *input_region;
40 struct zwlr_layer_surface_v1 *layer_surface; 54 struct zwlr_layer_surface_v1 *layer_surface;
41 55
42 bool run_display; 56 bool run_display;
43 uint32_t width, height; 57 uint32_t width, height;
44 int32_t scale;
45 struct pool_buffer buffers[2]; 58 struct pool_buffer buffers[2];
46 struct pool_buffer *current_buffer; 59 struct pool_buffer *current_buffer;
47}; 60};
@@ -65,8 +78,8 @@ bool is_valid_color(const char *color) {
65} 78}
66 79
67static void render_frame(struct swaybg_state *state) { 80static void render_frame(struct swaybg_state *state) {
68 int buffer_width = state->width * state->scale, 81 int buffer_width = state->width * state->output->scale,
69 buffer_height = state->height * state->scale; 82 buffer_height = state->height * state->output->scale;
70 state->current_buffer = get_next_buffer(state->shm, 83 state->current_buffer = get_next_buffer(state->shm,
71 state->buffers, buffer_width, buffer_height); 84 state->buffers, buffer_width, buffer_height);
72 if (!state->current_buffer) { 85 if (!state->current_buffer) {
@@ -89,7 +102,7 @@ static void render_frame(struct swaybg_state *state) {
89 state->args->mode, buffer_width, buffer_height); 102 state->args->mode, buffer_width, buffer_height);
90 } 103 }
91 104
92 wl_surface_set_buffer_scale(state->surface, state->scale); 105 wl_surface_set_buffer_scale(state->surface, state->output->scale);
93 wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); 106 wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0);
94 wl_surface_damage(state->surface, 0, 0, state->width, state->height); 107 wl_surface_damage(state->surface, 0, 0, state->width, state->height);
95 wl_surface_commit(state->surface); 108 wl_surface_commit(state->surface);
@@ -148,10 +161,14 @@ static void output_done(void *data, struct wl_output *output) {
148 // Who cares 161 // Who cares
149} 162}
150 163
151static void output_scale(void *data, struct wl_output *output, int32_t factor) { 164static void output_scale(void *data, struct wl_output *wl_output,
152 struct swaybg_state *state = data; 165 int32_t scale) {
153 state->scale = factor; 166 struct swaybg_output *output = data;
154 if (state->run_display) { 167 struct swaybg_state *state = output->state;
168
169 output->scale = scale;
170
171 if (state->output == output && state->run_display) {
155 render_frame(state); 172 render_frame(state);
156 } 173 }
157} 174}
@@ -163,26 +180,65 @@ static const struct wl_output_listener output_listener = {
163 .scale = output_scale, 180 .scale = output_scale,
164}; 181};
165 182
183static void xdg_output_handle_logical_position(void *data,
184 struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) {
185 // Who cares
186}
187
188static void xdg_output_handle_logical_size(void *data,
189 struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) {
190 // Who cares
191}
192
193static void xdg_output_handle_name(void *data,
194 struct zxdg_output_v1 *xdg_output, const char *name) {
195 struct swaybg_output *output = data;
196 struct swaybg_state *state = output->state;
197 if (strcmp(name, state->args->output) == 0) {
198 assert(state->output == NULL);
199 state->output = output;
200 }
201}
202
203static void xdg_output_handle_description(void *data,
204 struct zxdg_output_v1 *xdg_output, const char *description) {
205 // Who cares
206}
207
208static void xdg_output_handle_done(void *data,
209 struct zxdg_output_v1 *xdg_output) {
210 // Who cares
211}
212
213static const struct zxdg_output_v1_listener xdg_output_listener = {
214 .logical_position = xdg_output_handle_logical_position,
215 .logical_size = xdg_output_handle_logical_size,
216 .name = xdg_output_handle_name,
217 .description = xdg_output_handle_description,
218 .done = xdg_output_handle_done,
219};
220
166static void handle_global(void *data, struct wl_registry *registry, 221static void handle_global(void *data, struct wl_registry *registry,
167 uint32_t name, const char *interface, uint32_t version) { 222 uint32_t name, const char *interface, uint32_t version) {
168 struct swaybg_state *state = data; 223 struct swaybg_state *state = data;
169 if (strcmp(interface, wl_compositor_interface.name) == 0) { 224 if (strcmp(interface, wl_compositor_interface.name) == 0) {
170 state->compositor = wl_registry_bind(registry, name, 225 state->compositor =
171 &wl_compositor_interface, 3); 226 wl_registry_bind(registry, name, &wl_compositor_interface, 3);
172 } else if (strcmp(interface, wl_shm_interface.name) == 0) { 227 } else if (strcmp(interface, wl_shm_interface.name) == 0) {
173 state->shm = wl_registry_bind(registry, name, 228 state->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
174 &wl_shm_interface, 1);
175 } else if (strcmp(interface, wl_output_interface.name) == 0) { 229 } else if (strcmp(interface, wl_output_interface.name) == 0) {
176 static int output_idx = 0; 230 struct swaybg_output *output = calloc(1, sizeof(struct swaybg_output));
177 if (output_idx == state->args->output_idx) { 231 output->state = state;
178 state->output = wl_registry_bind(registry, name, 232 output->wl_output =
179 &wl_output_interface, 3); 233 wl_registry_bind(registry, name, &wl_output_interface, 3);
180 wl_output_add_listener(state->output, &output_listener, state); 234 wl_output_add_listener(output->wl_output, &output_listener, output);
181 } 235 wl_list_insert(&state->outputs, &output->link);
182 output_idx++;
183 } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { 236 } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
184 state->layer_shell = wl_registry_bind( 237 state->layer_shell =
185 registry, name, &zwlr_layer_shell_v1_interface, 1); 238 wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
239 } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
240 state->xdg_output_manager = wl_registry_bind(registry, name,
241 &zxdg_output_manager_v1_interface, 2);
186 } 242 }
187} 243}
188 244
@@ -197,17 +253,19 @@ static const struct wl_registry_listener registry_listener = {
197}; 253};
198 254
199int main(int argc, const char **argv) { 255int main(int argc, const char **argv) {
200 struct swaybg_args args = {0};
201 struct swaybg_state state = {0};
202 state.args = &args;
203 wlr_log_init(WLR_DEBUG, NULL); 256 wlr_log_init(WLR_DEBUG, NULL);
204 257
258 struct swaybg_args args = {0};
259 struct swaybg_state state = { .args = &args };
260 wl_list_init(&state.outputs);
261
205 if (argc < 4 || argc > 5) { 262 if (argc < 4 || argc > 5) {
206 wlr_log(WLR_ERROR, "Do not run this program manually. " 263 wlr_log(WLR_ERROR, "Do not run this program manually. "
207 "See man 5 sway and look for output options."); 264 "See `man 5 sway-output` and look for background options.");
208 return 1; 265 return 1;
209 } 266 }
210 args.output_idx = atoi(argv[1]); 267
268 args.output = argv[1];
211 args.path = argv[2]; 269 args.path = argv[2];
212 270
213 args.mode = parse_background_mode(argv[3]); 271 args.mode = parse_background_mode(argv[3]);
@@ -232,20 +290,36 @@ int main(int argc, const char **argv) {
232 struct wl_registry *registry = wl_display_get_registry(state.display); 290 struct wl_registry *registry = wl_display_get_registry(state.display);
233 wl_registry_add_listener(registry, &registry_listener, &state); 291 wl_registry_add_listener(registry, &registry_listener, &state);
234 wl_display_roundtrip(state.display); 292 wl_display_roundtrip(state.display);
235 assert(state.compositor && state.layer_shell && state.output && state.shm); 293 if (state.compositor == NULL || state.shm == NULL ||
294 state.layer_shell == NULL || state.xdg_output_manager == NULL) {
295 wlr_log(WLR_ERROR, "Missing a required Wayland interface");
296 return 1;
297 }
236 298
237 // Second roundtrip to get output properties 299 struct swaybg_output *output;
300 wl_list_for_each(output, &state.outputs, link) {
301 output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
302 state.xdg_output_manager, output->wl_output);
303 zxdg_output_v1_add_listener(output->xdg_output,
304 &xdg_output_listener, output);
305 }
306 // Second roundtrip to get xdg_output properties
238 wl_display_roundtrip(state.display); 307 wl_display_roundtrip(state.display);
308 if (state.output == NULL) {
309 wlr_log(WLR_ERROR, "Cannot find output '%s'", args.output);
310 return 1;
311 }
239 312
240 state.surface = wl_compositor_create_surface(state.compositor); 313 state.surface = wl_compositor_create_surface(state.compositor);
241 assert(state.surface); 314 assert(state.surface);
242 315
316 // Empty input region
243 state.input_region = wl_compositor_create_region(state.compositor); 317 state.input_region = wl_compositor_create_region(state.compositor);
244 assert(state.input_region); 318 assert(state.input_region);
245 wl_surface_set_input_region(state.surface, state.input_region); 319 wl_surface_set_input_region(state.surface, state.input_region);
246 320
247 state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( 321 state.layer_surface = zwlr_layer_shell_v1_get_layer_surface(
248 state.layer_shell, state.surface, state.output, 322 state.layer_shell, state.surface, state.output->wl_output,
249 ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); 323 ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper");
250 assert(state.layer_surface); 324 assert(state.layer_surface);
251 325
@@ -265,5 +339,6 @@ int main(int argc, const char **argv) {
265 while (wl_display_dispatch(state.display) != -1 && state.run_display) { 339 while (wl_display_dispatch(state.display) != -1 && state.run_display) {
266 // This space intentionally left blank 340 // This space intentionally left blank
267 } 341 }
342
268 return 0; 343 return 0;
269} 344}