aboutsummaryrefslogtreecommitdiffstats
path: root/swaybg
diff options
context:
space:
mode:
Diffstat (limited to 'swaybg')
-rw-r--r--swaybg/main.c75
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
138static void render_frame(struct swaybg_state *state) { 140static 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
220static 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
226static 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
231static void output_done(void *data, struct wl_output *output) {
232 // Who cares
233}
234
235static 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
243struct wl_output_listener output_listener = {
244 .geometry = output_geometry,
245 .mode = output_mode,
246 .done = output_done,
247 .scale = output_scale,
248};
249
217static void handle_global(void *data, struct wl_registry *registry, 250static 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));