diff options
author | Tony Crisci <tony@dubstepdish.com> | 2018-04-04 00:20:44 -0400 |
---|---|---|
committer | Tony Crisci <tony@dubstepdish.com> | 2018-04-04 00:20:44 -0400 |
commit | 741e3959e30283f5f699f7e9fa6620e3578b9c76 (patch) | |
tree | 8489f010c2f3e112722e7b999bacef18dfe418ef /swaybg | |
parent | simplify container close (diff) | |
parent | Merge pull request #1722 from swaywm/swaybar-hidpi (diff) | |
download | sway-741e3959e30283f5f699f7e9fa6620e3578b9c76.tar.gz sway-741e3959e30283f5f699f7e9fa6620e3578b9c76.tar.zst sway-741e3959e30283f5f699f7e9fa6620e3578b9c76.zip |
Merge branch 'wlroots' into split-containers2
Diffstat (limited to 'swaybg')
-rw-r--r-- | swaybg/main.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/swaybg/main.c b/swaybg/main.c index 203082f6..c282a707 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -43,10 +43,12 @@ struct swaybg_state { | |||
43 | 43 | ||
44 | struct wl_output *output; | 44 | struct wl_output *output; |
45 | struct wl_surface *surface; | 45 | struct wl_surface *surface; |
46 | struct wl_region *input_region; | ||
46 | struct zwlr_layer_surface_v1 *layer_surface; | 47 | struct zwlr_layer_surface_v1 *layer_surface; |
47 | 48 | ||
48 | bool run_display; | 49 | bool run_display; |
49 | uint32_t width, height; | 50 | uint32_t width, height; |
51 | int32_t scale; | ||
50 | struct pool_buffer buffers[2]; | 52 | struct pool_buffer buffers[2]; |
51 | struct pool_buffer *current_buffer; | 53 | struct pool_buffer *current_buffer; |
52 | }; | 54 | }; |
@@ -74,52 +76,53 @@ static void render_image(struct swaybg_state *state) { | |||
74 | cairo_surface_t *image = state->context.image; | 76 | cairo_surface_t *image = state->context.image; |
75 | double width = cairo_image_surface_get_width(image); | 77 | double width = cairo_image_surface_get_width(image); |
76 | double height = cairo_image_surface_get_height(image); | 78 | double height = cairo_image_surface_get_height(image); |
77 | int wwidth = state->width; | 79 | int buffer_width = state->width * state->scale; |
78 | int wheight = state->height; | 80 | int buffer_height = state->height * state->scale; |
79 | 81 | ||
80 | switch (state->args->mode) { | 82 | switch (state->args->mode) { |
81 | case BACKGROUND_MODE_STRETCH: | 83 | case BACKGROUND_MODE_STRETCH: |
82 | cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); | 84 | cairo_scale(cairo, (double)buffer_width / width, |
85 | (double)buffer_height / height); | ||
83 | cairo_set_source_surface(cairo, image, 0, 0); | 86 | cairo_set_source_surface(cairo, image, 0, 0); |
84 | break; | 87 | break; |
85 | case BACKGROUND_MODE_FILL: { | 88 | case BACKGROUND_MODE_FILL: { |
86 | double window_ratio = (double)wwidth / wheight; | 89 | double window_ratio = (double)buffer_width / buffer_height; |
87 | double bg_ratio = width / height; | 90 | double bg_ratio = width / height; |
88 | 91 | ||
89 | if (window_ratio > bg_ratio) { | 92 | if (window_ratio > bg_ratio) { |
90 | double scale = (double)wwidth / width; | 93 | double scale = (double)buffer_width / width; |
91 | cairo_scale(cairo, scale, scale); | 94 | cairo_scale(cairo, scale, scale); |
92 | cairo_set_source_surface(cairo, image, | 95 | cairo_set_source_surface(cairo, image, |
93 | 0, (double)wheight / 2 / scale - height / 2); | 96 | 0, (double)buffer_height / 2 / scale - height / 2); |
94 | } else { | 97 | } else { |
95 | double scale = (double)wheight / height; | 98 | double scale = (double)buffer_height / height; |
96 | cairo_scale(cairo, scale, scale); | 99 | cairo_scale(cairo, scale, scale); |
97 | cairo_set_source_surface(cairo, image, | 100 | cairo_set_source_surface(cairo, image, |
98 | (double)wwidth / 2 / scale - width / 2, 0); | 101 | (double)buffer_width / 2 / scale - width / 2, 0); |
99 | } | 102 | } |
100 | break; | 103 | break; |
101 | } | 104 | } |
102 | case BACKGROUND_MODE_FIT: { | 105 | case BACKGROUND_MODE_FIT: { |
103 | double window_ratio = (double)wwidth / wheight; | 106 | double window_ratio = (double)buffer_width / buffer_height; |
104 | double bg_ratio = width / height; | 107 | double bg_ratio = width / height; |
105 | 108 | ||
106 | if (window_ratio > bg_ratio) { | 109 | if (window_ratio > bg_ratio) { |
107 | double scale = (double)wheight / height; | 110 | double scale = (double)buffer_height / height; |
108 | cairo_scale(cairo, scale, scale); | 111 | cairo_scale(cairo, scale, scale); |
109 | cairo_set_source_surface(cairo, image, | 112 | cairo_set_source_surface(cairo, image, |
110 | (double)wwidth / 2 / scale - width / 2, 0); | 113 | (double)buffer_width / 2 / scale - width / 2, 0); |
111 | } else { | 114 | } else { |
112 | double scale = (double)wwidth / width; | 115 | double scale = (double)buffer_width / width; |
113 | cairo_scale(cairo, scale, scale); | 116 | cairo_scale(cairo, scale, scale); |
114 | cairo_set_source_surface(cairo, image, | 117 | cairo_set_source_surface(cairo, image, |
115 | 0, (double)wheight / 2 / scale - height / 2); | 118 | 0, (double)buffer_height / 2 / scale - height / 2); |
116 | } | 119 | } |
117 | break; | 120 | break; |
118 | } | 121 | } |
119 | case BACKGROUND_MODE_CENTER: | 122 | case BACKGROUND_MODE_CENTER: |
120 | cairo_set_source_surface(cairo, image, | 123 | cairo_set_source_surface(cairo, image, |
121 | (double)wwidth / 2 - width / 2, | 124 | (double)buffer_width / 2 - width / 2, |
122 | (double)wheight / 2 - height / 2); | 125 | (double)buffer_height / 2 - height / 2); |
123 | break; | 126 | break; |
124 | case BACKGROUND_MODE_TILE: { | 127 | case BACKGROUND_MODE_TILE: { |
125 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | 128 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); |
@@ -135,8 +138,8 @@ static void render_image(struct swaybg_state *state) { | |||
135 | } | 138 | } |
136 | 139 | ||
137 | static void render_frame(struct swaybg_state *state) { | 140 | static void render_frame(struct swaybg_state *state) { |
138 | state->current_buffer = get_next_buffer(state->shm, | 141 | state->current_buffer = get_next_buffer(state->shm, state->buffers, |
139 | state->buffers, state->width, state->height); | 142 | state->width * state->scale, state->height * state->scale); |
140 | cairo_t *cairo = state->current_buffer->cairo; | 143 | cairo_t *cairo = state->current_buffer->cairo; |
141 | 144 | ||
142 | switch (state->args->mode) { | 145 | switch (state->args->mode) { |
@@ -149,6 +152,7 @@ static void render_frame(struct swaybg_state *state) { | |||
149 | break; | 152 | break; |
150 | } | 153 | } |
151 | 154 | ||
155 | wl_surface_set_buffer_scale(state->surface, state->scale); | ||
152 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); | 156 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); |
153 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); | 157 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); |
154 | wl_surface_commit(state->surface); | 158 | wl_surface_commit(state->surface); |
@@ -204,6 +208,7 @@ static void layer_surface_closed(void *data, | |||
204 | struct swaybg_state *state = data; | 208 | struct swaybg_state *state = data; |
205 | zwlr_layer_surface_v1_destroy(state->layer_surface); | 209 | zwlr_layer_surface_v1_destroy(state->layer_surface); |
206 | wl_surface_destroy(state->surface); | 210 | wl_surface_destroy(state->surface); |
211 | wl_region_destroy(state->input_region); | ||
207 | state->run_display = false; | 212 | state->run_display = false; |
208 | } | 213 | } |
209 | 214 | ||
@@ -212,12 +217,42 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
212 | .closed = layer_surface_closed, | 217 | .closed = layer_surface_closed, |
213 | }; | 218 | }; |
214 | 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 | |||
215 | static void handle_global(void *data, struct wl_registry *registry, | 250 | static void handle_global(void *data, struct wl_registry *registry, |
216 | uint32_t name, const char *interface, uint32_t version) { | 251 | uint32_t name, const char *interface, uint32_t version) { |
217 | struct swaybg_state *state = data; | 252 | struct swaybg_state *state = data; |
218 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | 253 | if (strcmp(interface, wl_compositor_interface.name) == 0) { |
219 | state->compositor = wl_registry_bind(registry, name, | 254 | state->compositor = wl_registry_bind(registry, name, |
220 | &wl_compositor_interface, 1); | 255 | &wl_compositor_interface, 3); |
221 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | 256 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { |
222 | state->shm = wl_registry_bind(registry, name, | 257 | state->shm = wl_registry_bind(registry, name, |
223 | &wl_shm_interface, 1); | 258 | &wl_shm_interface, 1); |
@@ -225,7 +260,8 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
225 | static int output_idx = 0; | 260 | static int output_idx = 0; |
226 | if (output_idx == state->args->output_idx) { | 261 | if (output_idx == state->args->output_idx) { |
227 | state->output = wl_registry_bind(registry, name, | 262 | state->output = wl_registry_bind(registry, name, |
228 | &wl_output_interface, 1); | 263 | &wl_output_interface, 3); |
264 | wl_output_add_listener(state->output, &output_listener, state); | ||
229 | } | 265 | } |
230 | output_idx++; | 266 | output_idx++; |
231 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | 267 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { |
@@ -287,8 +323,14 @@ int main(int argc, const char **argv) { | |||
287 | wl_display_roundtrip(state.display); | 323 | wl_display_roundtrip(state.display); |
288 | assert(state.compositor && state.layer_shell && state.output && state.shm); | 324 | assert(state.compositor && state.layer_shell && state.output && state.shm); |
289 | 325 | ||
326 | // Second roundtrip to get output properties | ||
327 | wl_display_roundtrip(state.display); | ||
328 | |||
290 | assert(state.surface = wl_compositor_create_surface(state.compositor)); | 329 | assert(state.surface = wl_compositor_create_surface(state.compositor)); |
291 | 330 | ||
331 | assert(state.input_region = wl_compositor_create_region(state.compositor)); | ||
332 | wl_surface_set_input_region(state.surface, state.input_region); | ||
333 | |||
292 | state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( | 334 | state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( |
293 | state.layer_shell, state.surface, state.output, | 335 | state.layer_shell, state.surface, state.output, |
294 | ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); | 336 | ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); |