diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-04-03 17:02:32 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-03 17:02:32 -0400 |
commit | 843e16847b36a6cf4f685d9dae5133f7f9b37030 (patch) | |
tree | 26f5af498e5f6a6d6926a6645c7098433a0f62f6 | |
parent | Merge pull request #1712 from RedSoxFan/workspace-number-names (diff) | |
parent | swaybg: rename w{width,height} to buffer_{width,height} (diff) | |
download | sway-843e16847b36a6cf4f685d9dae5133f7f9b37030.tar.gz sway-843e16847b36a6cf4f685d9dae5133f7f9b37030.tar.zst sway-843e16847b36a6cf4f685d9dae5133f7f9b37030.zip |
Merge pull request #1713 from emersion/swaybg-hidpi
swaybg: add HiDPI support
-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 203082f6..25a1d73a 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -47,6 +47,7 @@ struct swaybg_state { | |||
47 | 47 | ||
48 | bool run_display; | 48 | bool run_display; |
49 | uint32_t width, height; | 49 | uint32_t width, height; |
50 | int32_t scale; | ||
50 | struct pool_buffer buffers[2]; | 51 | struct pool_buffer buffers[2]; |
51 | struct pool_buffer *current_buffer; | 52 | struct pool_buffer *current_buffer; |
52 | }; | 53 | }; |
@@ -74,52 +75,53 @@ static void render_image(struct swaybg_state *state) { | |||
74 | cairo_surface_t *image = state->context.image; | 75 | cairo_surface_t *image = state->context.image; |
75 | double width = cairo_image_surface_get_width(image); | 76 | double width = cairo_image_surface_get_width(image); |
76 | double height = cairo_image_surface_get_height(image); | 77 | double height = cairo_image_surface_get_height(image); |
77 | int wwidth = state->width; | 78 | int buffer_width = state->width * state->scale; |
78 | int wheight = state->height; | 79 | int buffer_height = state->height * state->scale; |
79 | 80 | ||
80 | switch (state->args->mode) { | 81 | switch (state->args->mode) { |
81 | case BACKGROUND_MODE_STRETCH: | 82 | case BACKGROUND_MODE_STRETCH: |
82 | cairo_scale(cairo, (double)wwidth / width, (double)wheight / height); | 83 | cairo_scale(cairo, (double)buffer_width / width, |
84 | (double)buffer_height / height); | ||
83 | cairo_set_source_surface(cairo, image, 0, 0); | 85 | cairo_set_source_surface(cairo, image, 0, 0); |
84 | break; | 86 | break; |
85 | case BACKGROUND_MODE_FILL: { | 87 | case BACKGROUND_MODE_FILL: { |
86 | double window_ratio = (double)wwidth / wheight; | 88 | double window_ratio = (double)buffer_width / buffer_height; |
87 | double bg_ratio = width / height; | 89 | double bg_ratio = width / height; |
88 | 90 | ||
89 | if (window_ratio > bg_ratio) { | 91 | if (window_ratio > bg_ratio) { |
90 | double scale = (double)wwidth / width; | 92 | double scale = (double)buffer_width / width; |
91 | cairo_scale(cairo, scale, scale); | 93 | cairo_scale(cairo, scale, scale); |
92 | cairo_set_source_surface(cairo, image, | 94 | cairo_set_source_surface(cairo, image, |
93 | 0, (double)wheight / 2 / scale - height / 2); | 95 | 0, (double)buffer_height / 2 / scale - height / 2); |
94 | } else { | 96 | } else { |
95 | double scale = (double)wheight / height; | 97 | double scale = (double)buffer_height / height; |
96 | cairo_scale(cairo, scale, scale); | 98 | cairo_scale(cairo, scale, scale); |
97 | cairo_set_source_surface(cairo, image, | 99 | cairo_set_source_surface(cairo, image, |
98 | (double)wwidth / 2 / scale - width / 2, 0); | 100 | (double)buffer_width / 2 / scale - width / 2, 0); |
99 | } | 101 | } |
100 | break; | 102 | break; |
101 | } | 103 | } |
102 | case BACKGROUND_MODE_FIT: { | 104 | case BACKGROUND_MODE_FIT: { |
103 | double window_ratio = (double)wwidth / wheight; | 105 | double window_ratio = (double)buffer_width / buffer_height; |
104 | double bg_ratio = width / height; | 106 | double bg_ratio = width / height; |
105 | 107 | ||
106 | if (window_ratio > bg_ratio) { | 108 | if (window_ratio > bg_ratio) { |
107 | double scale = (double)wheight / height; | 109 | double scale = (double)buffer_height / height; |
108 | cairo_scale(cairo, scale, scale); | 110 | cairo_scale(cairo, scale, scale); |
109 | cairo_set_source_surface(cairo, image, | 111 | cairo_set_source_surface(cairo, image, |
110 | (double)wwidth / 2 / scale - width / 2, 0); | 112 | (double)buffer_width / 2 / scale - width / 2, 0); |
111 | } else { | 113 | } else { |
112 | double scale = (double)wwidth / width; | 114 | double scale = (double)buffer_width / width; |
113 | cairo_scale(cairo, scale, scale); | 115 | cairo_scale(cairo, scale, scale); |
114 | cairo_set_source_surface(cairo, image, | 116 | cairo_set_source_surface(cairo, image, |
115 | 0, (double)wheight / 2 / scale - height / 2); | 117 | 0, (double)buffer_height / 2 / scale - height / 2); |
116 | } | 118 | } |
117 | break; | 119 | break; |
118 | } | 120 | } |
119 | case BACKGROUND_MODE_CENTER: | 121 | case BACKGROUND_MODE_CENTER: |
120 | cairo_set_source_surface(cairo, image, | 122 | cairo_set_source_surface(cairo, image, |
121 | (double)wwidth / 2 - width / 2, | 123 | (double)buffer_width / 2 - width / 2, |
122 | (double)wheight / 2 - height / 2); | 124 | (double)buffer_height / 2 - height / 2); |
123 | break; | 125 | break; |
124 | case BACKGROUND_MODE_TILE: { | 126 | case BACKGROUND_MODE_TILE: { |
125 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | 127 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); |
@@ -135,8 +137,8 @@ static void render_image(struct swaybg_state *state) { | |||
135 | } | 137 | } |
136 | 138 | ||
137 | static void render_frame(struct swaybg_state *state) { | 139 | static void render_frame(struct swaybg_state *state) { |
138 | state->current_buffer = get_next_buffer(state->shm, | 140 | state->current_buffer = get_next_buffer(state->shm, state->buffers, |
139 | state->buffers, state->width, state->height); | 141 | state->width * state->scale, state->height * state->scale); |
140 | cairo_t *cairo = state->current_buffer->cairo; | 142 | cairo_t *cairo = state->current_buffer->cairo; |
141 | 143 | ||
142 | switch (state->args->mode) { | 144 | switch (state->args->mode) { |
@@ -149,6 +151,7 @@ static void render_frame(struct swaybg_state *state) { | |||
149 | break; | 151 | break; |
150 | } | 152 | } |
151 | 153 | ||
154 | wl_surface_set_buffer_scale(state->surface, state->scale); | ||
152 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); | 155 | wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); |
153 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); | 156 | wl_surface_damage(state->surface, 0, 0, state->width, state->height); |
154 | wl_surface_commit(state->surface); | 157 | wl_surface_commit(state->surface); |
@@ -212,12 +215,42 @@ struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
212 | .closed = layer_surface_closed, | 215 | .closed = layer_surface_closed, |
213 | }; | 216 | }; |
214 | 217 | ||
218 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | ||
219 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | ||
220 | const char *make, const char *model, int32_t transform) { | ||
221 | // Who cares | ||
222 | } | ||
223 | |||
224 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | ||
225 | int32_t width, int32_t height, int32_t refresh) { | ||
226 | // Who cares | ||
227 | } | ||
228 | |||
229 | static void output_done(void *data, struct wl_output *output) { | ||
230 | // Who cares | ||
231 | } | ||
232 | |||
233 | static void output_scale(void *data, struct wl_output *output, int32_t factor) { | ||
234 | struct swaybg_state *state = data; | ||
235 | state->scale = factor; | ||
236 | if (state->run_display) { | ||
237 | render_frame(state); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | struct wl_output_listener output_listener = { | ||
242 | .geometry = output_geometry, | ||
243 | .mode = output_mode, | ||
244 | .done = output_done, | ||
245 | .scale = output_scale, | ||
246 | }; | ||
247 | |||
215 | static void handle_global(void *data, struct wl_registry *registry, | 248 | static void handle_global(void *data, struct wl_registry *registry, |
216 | uint32_t name, const char *interface, uint32_t version) { | 249 | uint32_t name, const char *interface, uint32_t version) { |
217 | struct swaybg_state *state = data; | 250 | struct swaybg_state *state = data; |
218 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | 251 | if (strcmp(interface, wl_compositor_interface.name) == 0) { |
219 | state->compositor = wl_registry_bind(registry, name, | 252 | state->compositor = wl_registry_bind(registry, name, |
220 | &wl_compositor_interface, 1); | 253 | &wl_compositor_interface, 3); |
221 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | 254 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { |
222 | state->shm = wl_registry_bind(registry, name, | 255 | state->shm = wl_registry_bind(registry, name, |
223 | &wl_shm_interface, 1); | 256 | &wl_shm_interface, 1); |
@@ -225,7 +258,8 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
225 | static int output_idx = 0; | 258 | static int output_idx = 0; |
226 | if (output_idx == state->args->output_idx) { | 259 | if (output_idx == state->args->output_idx) { |
227 | state->output = wl_registry_bind(registry, name, | 260 | state->output = wl_registry_bind(registry, name, |
228 | &wl_output_interface, 1); | 261 | &wl_output_interface, 3); |
262 | wl_output_add_listener(state->output, &output_listener, state); | ||
229 | } | 263 | } |
230 | output_idx++; | 264 | output_idx++; |
231 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | 265 | } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { |
@@ -287,6 +321,9 @@ int main(int argc, const char **argv) { | |||
287 | wl_display_roundtrip(state.display); | 321 | wl_display_roundtrip(state.display); |
288 | assert(state.compositor && state.layer_shell && state.output && state.shm); | 322 | assert(state.compositor && state.layer_shell && state.output && state.shm); |
289 | 323 | ||
324 | // Second roundtrip to get output properties | ||
325 | wl_display_roundtrip(state.display); | ||
326 | |||
290 | assert(state.surface = wl_compositor_create_surface(state.compositor)); | 327 | assert(state.surface = wl_compositor_create_surface(state.compositor)); |
291 | 328 | ||
292 | state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( | 329 | state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( |