diff options
Diffstat (limited to 'swaybg')
-rw-r--r-- | swaybg/main.c | 75 |
1 files changed, 56 insertions, 19 deletions
diff --git a/swaybg/main.c b/swaybg/main.c index b21415b2..c282a707 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -48,6 +48,7 @@ struct swaybg_state { | |||
48 | 48 | ||
49 | bool run_display; | 49 | bool run_display; |
50 | uint32_t width, height; | 50 | uint32_t width, height; |
51 | int32_t scale; | ||
51 | struct pool_buffer buffers[2]; | 52 | struct pool_buffer buffers[2]; |
52 | struct pool_buffer *current_buffer; | 53 | struct pool_buffer *current_buffer; |
53 | }; | 54 | }; |
@@ -75,52 +76,53 @@ static void render_image(struct swaybg_state *state) { | |||
75 | cairo_surface_t *image = state->context.image; | 76 | cairo_surface_t *image = state->context.image; |
76 | double width = cairo_image_surface_get_width(image); | 77 | double width = cairo_image_surface_get_width(image); |
77 | double height = cairo_image_surface_get_height(image); | 78 | double height = cairo_image_surface_get_height(image); |
78 | int wwidth = state->width; | 79 | int buffer_width = state->width * state->scale; |
79 | int wheight = state->height; | 80 | int buffer_height = state->height * state->scale; |
80 | 81 | ||
81 | switch (state->args->mode) { | 82 | switch (state->args->mode) { |
82 | case BACKGROUND_MODE_STRETCH: | 83 | case BACKGROUND_MODE_STRETCH: |
83 | cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); | 84 | cairo_scale(cairo, (double)buffer_width / width, |
85 | (double)buffer_height / height); | ||
84 | cairo_set_source_surface(cairo, image, 0, 0); | 86 | cairo_set_source_surface(cairo, image, 0, 0); |
85 | break; | 87 | break; |
86 | case BACKGROUND_MODE_FILL: { | 88 | case BACKGROUND_MODE_FILL: { |
87 | double window_ratio = (double)wwidth / wheight; | 89 | double window_ratio = (double)buffer_width / buffer_height; |
88 | double bg_ratio = width / height; | 90 | double bg_ratio = width / height; |
89 | 91 | ||
90 | if (window_ratio > bg_ratio) { | 92 | if (window_ratio > bg_ratio) { |
91 | double scale = (double)wwidth / width; | 93 | double scale = (double)buffer_width / width; |
92 | cairo_scale(cairo, scale, scale); | 94 | cairo_scale(cairo, scale, scale); |
93 | cairo_set_source_surface(cairo, image, | 95 | cairo_set_source_surface(cairo, image, |
94 | 0, (double)wheight / 2 / scale - height / 2); | 96 | 0, (double)buffer_height / 2 / scale - height / 2); |
95 | } else { | 97 | } else { |
96 | double scale = (double)wheight / height; | 98 | double scale = (double)buffer_height / height; |
97 | cairo_scale(cairo, scale, scale); | 99 | cairo_scale(cairo, scale, scale); |
98 | cairo_set_source_surface(cairo, image, | 100 | cairo_set_source_surface(cairo, image, |
99 | (double)wwidth / 2 / scale - width / 2, 0); | 101 | (double)buffer_width / 2 / scale - width / 2, 0); |
100 | } | 102 | } |
101 | break; | 103 | break; |
102 | } | 104 | } |
103 | case BACKGROUND_MODE_FIT: { | 105 | case BACKGROUND_MODE_FIT: { |
104 | double window_ratio = (double)wwidth / wheight; | 106 | double window_ratio = (double)buffer_width / buffer_height; |
105 | double bg_ratio = width / height; | 107 | double bg_ratio = width / height; |
106 | 108 | ||
107 | if (window_ratio > bg_ratio) { | 109 | if (window_ratio > bg_ratio) { |
108 | double scale = (double)wheight / height; | 110 | double scale = (double)buffer_height / height; |
109 | cairo_scale(cairo, scale, scale); | 111 | cairo_scale(cairo, scale, scale); |
110 | cairo_set_source_surface(cairo, image, | 112 | cairo_set_source_surface(cairo, image, |
111 | (double)wwidth / 2 / scale - width / 2, 0); | 113 | (double)buffer_width / 2 / scale - width / 2, 0); |
112 | } else { | 114 | } else { |
113 | double scale = (double)wwidth / width; | 115 | double scale = (double)buffer_width / width; |
114 | cairo_scale(cairo, scale, scale); | 116 | cairo_scale(cairo, scale, scale); |
115 | cairo_set_source_surface(cairo, image, | 117 | cairo_set_source_surface(cairo, image, |
116 | 0, (double)wheight / 2 / scale - height / 2); | 118 | 0, (double)buffer_height / 2 / scale - height / 2); |
117 | } | 119 | } |
118 | break; | 120 | break; |
119 | } | 121 | } |
120 | case BACKGROUND_MODE_CENTER: | 122 | case BACKGROUND_MODE_CENTER: |
121 | cairo_set_source_surface(cairo, image, | 123 | cairo_set_source_surface(cairo, image, |
122 | (double)wwidth / 2 - width / 2, | 124 | (double)buffer_width / 2 - width / 2, |
123 | (double)wheight / 2 - height / 2); | 125 | (double)buffer_height / 2 - height / 2); |
124 | break; | 126 | break; |
125 | case BACKGROUND_MODE_TILE: { | 127 | case BACKGROUND_MODE_TILE: { |
126 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | 128 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); |
@@ -136,8 +138,8 @@ static void render_image(struct swaybg_state *state) { | |||
136 | } | 138 | } |
137 | 139 | ||
138 | static void render_frame(struct swaybg_state *state) { | 140 | static void render_frame(struct swaybg_state *state) { |
139 | state->current_buffer = get_next_buffer(state->shm, | 141 | state->current_buffer = get_next_buffer(state->shm, state->buffers, |
140 | state->buffers, state->width, state->height); | 142 | state->width * state->scale, state->height * state->scale); |
141 | cairo_t *cairo = state->current_buffer->cairo; | 143 | cairo_t *cairo = state->current_buffer->cairo; |
142 | 144 | ||
143 | switch (state->args->mode) { | 145 | switch (state->args->mode) { |
@@ -150,6 +152,7 @@ static void render_frame(struct swaybg_state *state) { | |||
150 | break; | 152 | break; |
151 | } | 153 | } |
152 | 154 | ||
155 | wl_surface_set_buffer_scale(state->surface, state->scale); | ||
153 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); | 156 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); |
154 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); | 157 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); |
155 | wl_surface_commit(state->surface); | 158 | wl_surface_commit(state->surface); |
@@ -214,12 +217,42 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
214 | .closed = layer_surface_closed, | 217 | .closed = layer_surface_closed, |
215 | }; | 218 | }; |
216 | 219 | ||
220 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | ||
221 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | ||
222 | const char *make, const char *model, int32_t transform) { | ||
223 | // Who cares | ||
224 | } | ||
225 | |||
226 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | ||
227 | int32_t width, int32_t height, int32_t refresh) { | ||
228 | // Who cares | ||
229 | } | ||
230 | |||
231 | static void output_done(void *data, struct wl_output *output) { | ||
232 | // Who cares | ||
233 | } | ||
234 | |||
235 | static void output_scale(void *data, struct wl_output *output, int32_t factor) { | ||
236 | struct swaybg_state *state = data; | ||
237 | state->scale = factor; | ||
238 | if (state->run_display) { | ||
239 | render_frame(state); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | struct wl_output_listener output_listener = { | ||
244 | .geometry = output_geometry, | ||
245 | .mode = output_mode, | ||
246 | .done = output_done, | ||
247 | .scale = output_scale, | ||
248 | }; | ||
249 | |||
217 | static void handle_global(void *data, struct wl_registry *registry, | 250 | static void handle_global(void *data, struct wl_registry *registry, |
218 | uint32_t name, const char *interface, uint32_t version) { | 251 | uint32_t name, const char *interface, uint32_t version) { |
219 | struct swaybg_state *state = data; | 252 | struct swaybg_state *state = data; |
220 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | 253 | if (strcmp(interface, wl_compositor_interface.name) == 0) { |
221 | state->compositor = wl_registry_bind(registry, name, | 254 | state->compositor = wl_registry_bind(registry, name, |
222 | &wl_compositor_interface, 1); | 255 | &wl_compositor_interface, 3); |
223 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | 256 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { |
224 | state->shm = wl_registry_bind(registry, name, | 257 | state->shm = wl_registry_bind(registry, name, |
225 | &wl_shm_interface, 1); | 258 | &wl_shm_interface, 1); |
@@ -227,7 +260,8 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
227 | static int output_idx = 0; | 260 | static int output_idx = 0; |
228 | if (output_idx == state->args->output_idx) { | 261 | if (output_idx == state->args->output_idx) { |
229 | state->output = wl_registry_bind(registry, name, | 262 | state->output = wl_registry_bind(registry, name, |
230 | &wl_output_interface, 1); | 263 | &wl_output_interface, 3); |
264 | wl_output_add_listener(state->output, &output_listener, state); | ||
231 | } | 265 | } |
232 | output_idx++; | 266 | output_idx++; |
233 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | 267 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { |
@@ -289,6 +323,9 @@ int main(int argc, const char **argv) { | |||
289 | wl_display_roundtrip(state.display); | 323 | wl_display_roundtrip(state.display); |
290 | assert(state.compositor && state.layer_shell && state.output && state.shm); | 324 | assert(state.compositor && state.layer_shell && state.output && state.shm); |
291 | 325 | ||
326 | // Second roundtrip to get output properties | ||
327 | wl_display_roundtrip(state.display); | ||
328 | |||
292 | assert(state.surface = wl_compositor_create_surface(state.compositor)); | 329 | assert(state.surface = wl_compositor_create_surface(state.compositor)); |
293 | 330 | ||
294 | assert(state.input_region = wl_compositor_create_region(state.compositor)); | 331 | assert(state.input_region = wl_compositor_create_region(state.compositor)); |