diff options
-rw-r--r-- | include/sway/input/seat.h | 7 | ||||
-rw-r--r-- | include/swaybar/bar.h | 1 | ||||
-rw-r--r-- | sway/config/output.c | 11 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 29 | ||||
-rw-r--r-- | sway/desktop/output.c | 40 | ||||
-rw-r--r-- | sway/input/cursor.c | 11 | ||||
-rw-r--r-- | sway/input/seat.c | 36 | ||||
-rw-r--r-- | sway/tree/layout.c | 16 | ||||
-rw-r--r-- | sway/tree/workspace.c | 18 | ||||
-rw-r--r-- | swaybar/bar.c | 89 | ||||
-rw-r--r-- | swaybar/i3bar.c | 5 | ||||
-rw-r--r-- | swaybar/render.c | 175 | ||||
-rw-r--r-- | swaybar/status_line.c | 6 | ||||
-rw-r--r-- | swaybg/main.c | 80 |
14 files changed, 386 insertions, 138 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index c780a52b..137fcd22 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _SWAY_INPUT_SEAT_H | 1 | #ifndef _SWAY_INPUT_SEAT_H |
2 | #define _SWAY_INPUT_SEAT_H | 2 | #define _SWAY_INPUT_SEAT_H |
3 | 3 | ||
4 | #include <wlr/types/wlr_layer_shell.h> | ||
4 | #include <wlr/types/wlr_seat.h> | 5 | #include <wlr/types/wlr_seat.h> |
5 | #include "sway/input/input-manager.h" | 6 | #include "sway/input/input-manager.h" |
6 | 7 | ||
@@ -28,6 +29,9 @@ struct sway_seat { | |||
28 | bool has_focus; | 29 | bool has_focus; |
29 | struct wl_list focus_stack; // list of containers in focus order | 30 | struct wl_list focus_stack; // list of containers in focus order |
30 | 31 | ||
32 | // If the focused layer is set, views cannot receive keyboard focus | ||
33 | struct wlr_layer_surface *focused_layer; | ||
34 | |||
31 | struct wl_listener focus_destroy; | 35 | struct wl_listener focus_destroy; |
32 | struct wl_listener new_container; | 36 | struct wl_listener new_container; |
33 | 37 | ||
@@ -57,6 +61,9 @@ void seat_set_focus(struct sway_seat *seat, struct sway_container *container); | |||
57 | void seat_set_focus_warp(struct sway_seat *seat, | 61 | void seat_set_focus_warp(struct sway_seat *seat, |
58 | struct sway_container *container, bool warp); | 62 | struct sway_container *container, bool warp); |
59 | 63 | ||
64 | void seat_set_focus_layer(struct sway_seat *seat, | ||
65 | struct wlr_layer_surface *layer); | ||
66 | |||
60 | struct sway_container *seat_get_focus(struct sway_seat *seat); | 67 | struct sway_container *seat_get_focus(struct sway_seat *seat); |
61 | 68 | ||
62 | /** | 69 | /** |
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 74292519..503b961c 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -58,6 +58,7 @@ struct swaybar_output { | |||
58 | bool focused; | 58 | bool focused; |
59 | 59 | ||
60 | uint32_t width, height; | 60 | uint32_t width, height; |
61 | int32_t scale; | ||
61 | struct pool_buffer buffers[2]; | 62 | struct pool_buffer buffers[2]; |
62 | struct pool_buffer *current_buffer; | 63 | struct pool_buffer *current_buffer; |
63 | }; | 64 | }; |
diff --git a/sway/config/output.c b/sway/config/output.c index c4b74ce2..1c298d37 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -123,11 +123,14 @@ void terminate_swaybg(pid_t pid) { | |||
123 | void apply_output_config(struct output_config *oc, struct sway_container *output) { | 123 | void apply_output_config(struct output_config *oc, struct sway_container *output) { |
124 | assert(output->type == C_OUTPUT); | 124 | assert(output->type == C_OUTPUT); |
125 | 125 | ||
126 | struct wlr_output_layout *output_layout = | ||
127 | root_container.sway_root->output_layout; | ||
126 | struct wlr_output *wlr_output = output->sway_output->wlr_output; | 128 | struct wlr_output *wlr_output = output->sway_output->wlr_output; |
129 | |||
127 | if (oc && oc->enabled == 0) { | 130 | if (oc && oc->enabled == 0) { |
131 | container_destroy(output); | ||
128 | wlr_output_layout_remove(root_container.sway_root->output_layout, | 132 | wlr_output_layout_remove(root_container.sway_root->output_layout, |
129 | wlr_output); | 133 | wlr_output); |
130 | container_destroy(output); | ||
131 | return; | 134 | return; |
132 | } | 135 | } |
133 | 136 | ||
@@ -148,11 +151,9 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
148 | // Find position for it | 151 | // Find position for it |
149 | if (oc && (oc->x != -1 || oc->y != -1)) { | 152 | if (oc && (oc->x != -1 || oc->y != -1)) { |
150 | wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); | 153 | wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); |
151 | wlr_output_layout_add(root_container.sway_root->output_layout, | 154 | wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); |
152 | wlr_output, oc->x, oc->y); | ||
153 | } else { | 155 | } else { |
154 | wlr_output_layout_add_auto(root_container.sway_root->output_layout, | 156 | wlr_output_layout_add_auto(output_layout, wlr_output); |
155 | wlr_output); | ||
156 | } | 157 | } |
157 | 158 | ||
158 | if (!oc || !oc->background) { | 159 | if (!oc || !oc->background) { |
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index c18f51c7..663ec7ba 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <wlr/types/wlr_output_damage.h> | 7 | #include <wlr/types/wlr_output_damage.h> |
8 | #include <wlr/types/wlr_output.h> | 8 | #include <wlr/types/wlr_output.h> |
9 | #include <wlr/util/log.h> | 9 | #include <wlr/util/log.h> |
10 | #include "sway/input/input-manager.h" | ||
11 | #include "sway/input/seat.h" | ||
10 | #include "sway/layers.h" | 12 | #include "sway/layers.h" |
11 | #include "sway/output.h" | 13 | #include "sway/output.h" |
12 | #include "sway/server.h" | 14 | #include "sway/server.h" |
@@ -187,6 +189,31 @@ void arrange_layers(struct sway_output *output) { | |||
187 | &usable_area, false); | 189 | &usable_area, false); |
188 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | 190 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], |
189 | &usable_area, false); | 191 | &usable_area, false); |
192 | |||
193 | // Find topmost keyboard interactive layer, if such a layer exists | ||
194 | uint32_t layers_above_shell[] = { | ||
195 | ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, | ||
196 | ZWLR_LAYER_SHELL_V1_LAYER_TOP, | ||
197 | }; | ||
198 | size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); | ||
199 | struct sway_layer_surface *layer, *topmost = NULL; | ||
200 | for (size_t i = 0; i < nlayers; ++i) { | ||
201 | wl_list_for_each_reverse(layer, | ||
202 | &output->layers[layers_above_shell[i]], link) { | ||
203 | if (layer->layer_surface->current.keyboard_interactive) { | ||
204 | topmost = layer; | ||
205 | break; | ||
206 | } | ||
207 | } | ||
208 | if (topmost != NULL) { | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | struct sway_seat *seat; | ||
214 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
215 | seat_set_focus_layer(seat, topmost ? topmost->layer_surface : NULL); | ||
216 | } | ||
190 | } | 217 | } |
191 | 218 | ||
192 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 219 | static void handle_output_destroy(struct wl_listener *listener, void *data) { |
@@ -251,6 +278,8 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
251 | sway_layer, map); | 278 | sway_layer, map); |
252 | struct sway_output *output = sway_layer->layer_surface->output->data; | 279 | struct sway_output *output = sway_layer->layer_surface->output->data; |
253 | wlr_output_damage_add_box(output->damage, &sway_layer->geo); | 280 | wlr_output_damage_add_box(output->damage, &sway_layer->geo); |
281 | wlr_surface_send_enter(sway_layer->layer_surface->surface, | ||
282 | sway_layer->layer_surface->output); | ||
254 | } | 283 | } |
255 | 284 | ||
256 | static void handle_unmap(struct wl_listener *listener, void *data) { | 285 | static void handle_unmap(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 96f23291..8a4fb4a2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -57,10 +57,7 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
57 | */ | 57 | */ |
58 | static bool surface_intersect_output(struct wlr_surface *surface, | 58 | static bool surface_intersect_output(struct wlr_surface *surface, |
59 | struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, | 59 | struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, |
60 | double lx, double ly, float rotation, struct wlr_box *box) { | 60 | double ox, double oy, float rotation, struct wlr_box *box) { |
61 | double ox = lx, oy = ly; | ||
62 | wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); | ||
63 | |||
64 | if (box != NULL) { | 61 | if (box != NULL) { |
65 | box->x = ox * wlr_output->scale; | 62 | box->x = ox * wlr_output->scale; |
66 | box->y = oy * wlr_output->scale; | 63 | box->y = oy * wlr_output->scale; |
@@ -69,7 +66,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, | |||
69 | } | 66 | } |
70 | 67 | ||
71 | struct wlr_box layout_box = { | 68 | struct wlr_box layout_box = { |
72 | .x = lx, .y = ly, | 69 | .x = wlr_output->lx + ox, .y = wlr_output->ly + oy, |
73 | .width = surface->current->width, .height = surface->current->height, | 70 | .width = surface->current->width, .height = surface->current->height, |
74 | }; | 71 | }; |
75 | wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); | 72 | wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); |
@@ -78,7 +75,7 @@ static bool surface_intersect_output(struct wlr_surface *surface, | |||
78 | 75 | ||
79 | static void render_surface(struct wlr_surface *surface, | 76 | static void render_surface(struct wlr_surface *surface, |
80 | struct wlr_output *wlr_output, struct timespec *when, | 77 | struct wlr_output *wlr_output, struct timespec *when, |
81 | double lx, double ly, float rotation) { | 78 | double ox, double oy, float rotation) { |
82 | struct wlr_renderer *renderer = | 79 | struct wlr_renderer *renderer = |
83 | wlr_backend_get_renderer(wlr_output->backend); | 80 | wlr_backend_get_renderer(wlr_output->backend); |
84 | 81 | ||
@@ -90,7 +87,7 @@ static void render_surface(struct wlr_surface *surface, | |||
90 | 87 | ||
91 | struct wlr_box box; | 88 | struct wlr_box box; |
92 | bool intersects = surface_intersect_output(surface, layout, wlr_output, | 89 | bool intersects = surface_intersect_output(surface, layout, wlr_output, |
93 | lx, ly, rotation, &box); | 90 | ox, oy, rotation, &box); |
94 | if (intersects) { | 91 | if (intersects) { |
95 | float matrix[9]; | 92 | float matrix[9]; |
96 | enum wl_output_transform transform = | 93 | enum wl_output_transform transform = |
@@ -113,7 +110,7 @@ static void render_surface(struct wlr_surface *surface, | |||
113 | surface->current->width, surface->current->height, rotation); | 110 | surface->current->width, surface->current->height, rotation); |
114 | 111 | ||
115 | render_surface(subsurface->surface, wlr_output, when, | 112 | render_surface(subsurface->surface, wlr_output, when, |
116 | lx + sx, ly + sy, rotation); | 113 | ox + sx, oy + sy, rotation); |
117 | } | 114 | } |
118 | } | 115 | } |
119 | 116 | ||
@@ -211,9 +208,7 @@ static void render_view(struct sway_container *view, void *data) { | |||
211 | } | 208 | } |
212 | } | 209 | } |
213 | 210 | ||
214 | static void render_layer(struct sway_output *output, | 211 | static void render_layer(struct sway_output *output, struct timespec *when, |
215 | const struct wlr_box *output_layout_box, | ||
216 | struct timespec *when, | ||
217 | struct wl_list *layer) { | 212 | struct wl_list *layer) { |
218 | struct sway_layer_surface *sway_layer; | 213 | struct sway_layer_surface *sway_layer; |
219 | wl_list_for_each(sway_layer, layer, link) { | 214 | wl_list_for_each(sway_layer, layer, link) { |
@@ -245,14 +240,15 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
245 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 240 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
246 | wlr_renderer_clear(renderer, clear_color); | 241 | wlr_renderer_clear(renderer, clear_color); |
247 | 242 | ||
248 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 243 | struct wlr_output_layout *output_layout = |
244 | root_container.sway_root->output_layout; | ||
249 | const struct wlr_box *output_box = | 245 | const struct wlr_box *output_box = |
250 | wlr_output_layout_get_box(layout, wlr_output); | 246 | wlr_output_layout_get_box(output_layout, wlr_output); |
251 | 247 | ||
252 | render_layer(output, output_box, when, | 248 | render_layer(output, when, |
253 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 249 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); |
254 | render_layer(output, output_box, when, | 250 | render_layer(output, when, |
255 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 251 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); |
256 | 252 | ||
257 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 253 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
258 | struct sway_container *focus = | 254 | struct sway_container *focus = |
@@ -262,7 +258,7 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
262 | focus = output->swayc->children->items[0]; | 258 | focus = output->swayc->children->items[0]; |
263 | } | 259 | } |
264 | struct sway_container *workspace = focus->type == C_WORKSPACE ? | 260 | struct sway_container *workspace = focus->type == C_WORKSPACE ? |
265 | focus : container_parent(focus, C_WORKSPACE); | 261 | focus : container_parent(focus, C_WORKSPACE); |
266 | 262 | ||
267 | struct render_data rdata = { | 263 | struct render_data rdata = { |
268 | .output = output, | 264 | .output = output, |
@@ -296,10 +292,10 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
296 | } | 292 | } |
297 | 293 | ||
298 | // TODO: Consider revising this when fullscreen windows are supported | 294 | // TODO: Consider revising this when fullscreen windows are supported |
299 | render_layer(output, output_box, when, | 295 | render_layer(output, when, |
300 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 296 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); |
301 | render_layer(output, output_box, when, | 297 | render_layer(output, when, |
302 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 298 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); |
303 | 299 | ||
304 | renderer_end: | 300 | renderer_end: |
305 | wlr_renderer_end(renderer); | 301 | wlr_renderer_end(renderer); |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 97b4473c..9229e92d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -180,13 +180,18 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
180 | double sx, sy; | 180 | double sx, sy; |
181 | struct sway_container *cont = | 181 | struct sway_container *cont = |
182 | container_at_cursor(cursor, &surface, &sx, &sy); | 182 | container_at_cursor(cursor, &surface, &sx, &sy); |
183 | if (surface && wlr_surface_is_layer_surface(surface)) { | ||
184 | struct wlr_layer_surface *layer = | ||
185 | wlr_layer_surface_from_wlr_surface(surface); | ||
186 | if (layer->current.keyboard_interactive) { | ||
187 | seat_set_focus_layer(cursor->seat, layer); | ||
188 | return; | ||
189 | } | ||
190 | } | ||
183 | // Avoid moving keyboard focus from a surface that accepts it to one | 191 | // Avoid moving keyboard focus from a surface that accepts it to one |
184 | // that does not unless the change would move us to a new workspace. | 192 | // that does not unless the change would move us to a new workspace. |
185 | // | 193 | // |
186 | // This prevents, for example, losing focus when clicking on swaybar. | 194 | // This prevents, for example, losing focus when clicking on swaybar. |
187 | // | ||
188 | // TODO: Replace this condition with something like | ||
189 | // !surface_accepts_keyboard_input | ||
190 | if (surface && cont && cont->type != C_VIEW) { | 195 | if (surface && cont && cont->type != C_VIEW) { |
191 | struct sway_container *new_ws = cont; | 196 | struct sway_container *new_ws = cont; |
192 | if (new_ws && new_ws->type != C_WORKSPACE) { | 197 | if (new_ws && new_ws->type != C_WORKSPACE) { |
diff --git a/sway/input/seat.c b/sway/input/seat.c index c326f176..4a99e9eb 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -352,8 +352,11 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
352 | 352 | ||
353 | void seat_set_focus_warp(struct sway_seat *seat, | 353 | void seat_set_focus_warp(struct sway_seat *seat, |
354 | struct sway_container *container, bool warp) { | 354 | struct sway_container *container, bool warp) { |
355 | struct sway_container *last_focus = seat_get_focus(seat); | 355 | if (seat->focused_layer) { |
356 | return; | ||
357 | } | ||
356 | 358 | ||
359 | struct sway_container *last_focus = seat_get_focus(seat); | ||
357 | if (container && last_focus == container) { | 360 | if (container && last_focus == container) { |
358 | return; | 361 | return; |
359 | } | 362 | } |
@@ -419,6 +422,37 @@ void seat_set_focus(struct sway_seat *seat, | |||
419 | seat_set_focus_warp(seat, container, true); | 422 | seat_set_focus_warp(seat, container, true); |
420 | } | 423 | } |
421 | 424 | ||
425 | void seat_set_focus_layer(struct sway_seat *seat, | ||
426 | struct wlr_layer_surface *layer) { | ||
427 | if (!layer) { | ||
428 | seat->focused_layer = NULL; | ||
429 | return; | ||
430 | } | ||
431 | if (seat->focused_layer == layer) { | ||
432 | return; | ||
433 | } | ||
434 | if (seat->has_focus) { | ||
435 | struct sway_container *focus = seat_get_focus(seat); | ||
436 | if (focus->type == C_VIEW) { | ||
437 | wlr_seat_keyboard_clear_focus(seat->wlr_seat); | ||
438 | view_set_activated(focus->sway_view, false); | ||
439 | } | ||
440 | } | ||
441 | if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { | ||
442 | seat->focused_layer = layer; | ||
443 | } | ||
444 | struct wlr_keyboard *keyboard = | ||
445 | wlr_seat_get_keyboard(seat->wlr_seat); | ||
446 | if (keyboard) { | ||
447 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | ||
448 | layer->surface, keyboard->keycodes, | ||
449 | keyboard->num_keycodes, &keyboard->modifiers); | ||
450 | } else { | ||
451 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, | ||
452 | layer->surface, NULL, 0, NULL); | ||
453 | } | ||
454 | } | ||
455 | |||
422 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, | 456 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |
423 | struct sway_container *container) { | 457 | struct sway_container *container) { |
424 | return seat_get_focus_by_type(seat, container, C_TYPES); | 458 | return seat_get_focus_by_type(seat, container, C_TYPES); |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index a46359bd..5abdbc32 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -18,10 +18,14 @@ | |||
18 | 18 | ||
19 | struct sway_container root_container; | 19 | struct sway_container root_container; |
20 | 20 | ||
21 | static void output_layout_change_notify(struct wl_listener *listener, | 21 | static void output_layout_handle_change(struct wl_listener *listener, |
22 | void *data) { | 22 | void *data) { |
23 | struct wlr_box *layout_box = wlr_output_layout_get_box( | 23 | struct wlr_output_layout *output_layout = |
24 | root_container.sway_root->output_layout, NULL); | 24 | root_container.sway_root->output_layout; |
25 | const struct wlr_box *layout_box = | ||
26 | wlr_output_layout_get_box(output_layout, NULL); | ||
27 | root_container.x = layout_box->x; | ||
28 | root_container.y = layout_box->y; | ||
25 | root_container.width = layout_box->width; | 29 | root_container.width = layout_box->width; |
26 | root_container.height = layout_box->height; | 30 | root_container.height = layout_box->height; |
27 | 31 | ||
@@ -33,8 +37,8 @@ static void output_layout_change_notify(struct wl_listener *listener, | |||
33 | } | 37 | } |
34 | struct sway_output *output = output_container->sway_output; | 38 | struct sway_output *output = output_container->sway_output; |
35 | 39 | ||
36 | struct wlr_box *output_box = wlr_output_layout_get_box( | 40 | const struct wlr_box *output_box = |
37 | root_container.sway_root->output_layout, output->wlr_output); | 41 | wlr_output_layout_get_box(output_layout, output->wlr_output); |
38 | if (!output_box) { | 42 | if (!output_box) { |
39 | continue; | 43 | continue; |
40 | } | 44 | } |
@@ -74,7 +78,7 @@ void layout_init(void) { | |||
74 | wl_signal_init(&root_container.sway_root->events.new_container); | 78 | wl_signal_init(&root_container.sway_root->events.new_container); |
75 | 79 | ||
76 | root_container.sway_root->output_layout_change.notify = | 80 | root_container.sway_root->output_layout_change.notify = |
77 | output_layout_change_notify; | 81 | output_layout_handle_change; |
78 | wl_signal_add(&root_container.sway_root->output_layout->events.change, | 82 | wl_signal_add(&root_container.sway_root->output_layout->events.change, |
79 | &root_container.sway_root->output_layout_change); | 83 | &root_container.sway_root->output_layout_change); |
80 | } | 84 | } |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 6ba3d973..316f01e4 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -139,6 +139,24 @@ char *workspace_next_name(const char *output_name) { | |||
139 | continue; | 139 | continue; |
140 | } | 140 | } |
141 | 141 | ||
142 | // If the command is workspace number <name>, isolate the name | ||
143 | if (strncmp(_target, "number ", strlen("number ")) == 0) { | ||
144 | size_t length = strlen(_target) - strlen("number ") + 1; | ||
145 | char *temp = malloc(length); | ||
146 | strncpy(temp, _target + strlen("number "), length - 1); | ||
147 | temp[length - 1] = '\0'; | ||
148 | free(_target); | ||
149 | _target = temp; | ||
150 | wlr_log(L_DEBUG, "Isolated name from workspace number: '%s'", _target); | ||
151 | |||
152 | // Make sure the workspace number doesn't already exist | ||
153 | if (workspace_by_number(_target)) { | ||
154 | free(_target); | ||
155 | free(dup); | ||
156 | continue; | ||
157 | } | ||
158 | } | ||
159 | |||
142 | // Make sure that the workspace doesn't already exist | 160 | // Make sure that the workspace doesn't already exist |
143 | if (workspace_by_name(_target)) { | 161 | if (workspace_by_name(_target)) { |
144 | free(_target); | 162 | free(_target); |
diff --git a/swaybar/bar.c b/swaybar/bar.c index fb417095..ea0141cc 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -69,11 +69,19 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | |||
69 | break; | 69 | break; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | int max_scale = 1; | ||
73 | struct swaybar_output *_output; | ||
74 | wl_list_for_each(_output, &bar->outputs, link) { | ||
75 | if (_output->scale > max_scale) { | ||
76 | max_scale = _output->scale; | ||
77 | } | ||
78 | } | ||
79 | wl_surface_set_buffer_scale(pointer->cursor_surface, max_scale); | ||
72 | wl_surface_attach(pointer->cursor_surface, | 80 | wl_surface_attach(pointer->cursor_surface, |
73 | wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); | 81 | wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0); |
74 | wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, | 82 | wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface, |
75 | pointer->cursor_image->hotspot_x, | 83 | pointer->cursor_image->hotspot_x / max_scale, |
76 | pointer->cursor_image->hotspot_y); | 84 | pointer->cursor_image->hotspot_y / max_scale); |
77 | wl_surface_commit(pointer->cursor_surface); | 85 | wl_surface_commit(pointer->cursor_surface); |
78 | } | 86 | } |
79 | 87 | ||
@@ -103,10 +111,12 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
103 | } | 111 | } |
104 | struct swaybar_hotspot *hotspot; | 112 | struct swaybar_hotspot *hotspot; |
105 | wl_list_for_each(hotspot, &output->hotspots, link) { | 113 | wl_list_for_each(hotspot, &output->hotspots, link) { |
106 | if (pointer->x >= hotspot->x | 114 | double x = pointer->x * output->scale; |
107 | && pointer->y >= hotspot->y | 115 | double y = pointer->y * output->scale; |
108 | && pointer->x < hotspot->x + hotspot->width | 116 | if (x >= hotspot->x |
109 | && pointer->y < hotspot->y + hotspot->height) { | 117 | && y >= hotspot->y |
118 | && x < hotspot->x + hotspot->width | ||
119 | && y < hotspot->y + hotspot->height) { | ||
110 | hotspot->callback(output, pointer->x, pointer->y, | 120 | hotspot->callback(output, pointer->x, pointer->y, |
111 | button, hotspot->data); | 121 | button, hotspot->data); |
112 | } | 122 | } |
@@ -197,12 +207,43 @@ const struct wl_seat_listener seat_listener = { | |||
197 | .name = seat_handle_name, | 207 | .name = seat_handle_name, |
198 | }; | 208 | }; |
199 | 209 | ||
210 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | ||
211 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | ||
212 | const char *make, const char *model, int32_t transform) { | ||
213 | // Who cares | ||
214 | } | ||
215 | |||
216 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | ||
217 | int32_t width, int32_t height, int32_t refresh) { | ||
218 | // Who cares | ||
219 | } | ||
220 | |||
221 | static void output_done(void *data, struct wl_output *output) { | ||
222 | // Who cares | ||
223 | } | ||
224 | |||
225 | static void output_scale(void *data, struct wl_output *wl_output, | ||
226 | int32_t factor) { | ||
227 | struct swaybar_output *output = data; | ||
228 | output->scale = factor; | ||
229 | if (output->surface) { | ||
230 | render_frame(output->bar, output); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | struct wl_output_listener output_listener = { | ||
235 | .geometry = output_geometry, | ||
236 | .mode = output_mode, | ||
237 | .done = output_done, | ||
238 | .scale = output_scale, | ||
239 | }; | ||
240 | |||
200 | static void handle_global(void *data, struct wl_registry *registry, | 241 | static void handle_global(void *data, struct wl_registry *registry, |
201 | uint32_t name, const char *interface, uint32_t version) { | 242 | uint32_t name, const char *interface, uint32_t version) { |
202 | struct swaybar *bar = data; | 243 | struct swaybar *bar = data; |
203 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | 244 | if (strcmp(interface, wl_compositor_interface.name) == 0) { |
204 | bar->compositor = wl_registry_bind(registry, name, | 245 | bar->compositor = wl_registry_bind(registry, name, |
205 | &wl_compositor_interface, 1); | 246 | &wl_compositor_interface, 3); |
206 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | 247 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { |
207 | bar->seat = wl_registry_bind(registry, name, | 248 | bar->seat = wl_registry_bind(registry, name, |
208 | &wl_seat_interface, 1); | 249 | &wl_seat_interface, 1); |
@@ -216,7 +257,9 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
216 | calloc(1, sizeof(struct swaybar_output)); | 257 | calloc(1, sizeof(struct swaybar_output)); |
217 | output->bar = bar; | 258 | output->bar = bar; |
218 | output->output = wl_registry_bind(registry, name, | 259 | output->output = wl_registry_bind(registry, name, |
219 | &wl_output_interface, 1); | 260 | &wl_output_interface, 3); |
261 | wl_output_add_listener(output->output, &output_listener, output); | ||
262 | output->scale = 1; | ||
220 | output->index = index++; | 263 | output->index = index++; |
221 | wl_list_init(&output->workspaces); | 264 | wl_list_init(&output->workspaces); |
222 | wl_list_init(&output->hotspots); | 265 | wl_list_init(&output->hotspots); |
@@ -256,24 +299,36 @@ void bar_setup(struct swaybar *bar, | |||
256 | bar->status = status_line_init(bar->config->status_command); | 299 | bar->status = status_line_init(bar->config->status_command); |
257 | } | 300 | } |
258 | 301 | ||
259 | assert(bar->display = wl_display_connect(NULL)); | 302 | bar->display = wl_display_connect(NULL); |
303 | assert(bar->display); | ||
260 | 304 | ||
261 | struct wl_registry *registry = wl_display_get_registry(bar->display); | 305 | struct wl_registry *registry = wl_display_get_registry(bar->display); |
262 | wl_registry_add_listener(registry, ®istry_listener, bar); | 306 | wl_registry_add_listener(registry, ®istry_listener, bar); |
263 | wl_display_roundtrip(bar->display); | 307 | wl_display_roundtrip(bar->display); |
264 | assert(bar->compositor && bar->layer_shell && bar->shm); | 308 | assert(bar->compositor && bar->layer_shell && bar->shm); |
309 | wl_display_roundtrip(bar->display); | ||
310 | |||
265 | struct swaybar_pointer *pointer = &bar->pointer; | 311 | struct swaybar_pointer *pointer = &bar->pointer; |
266 | 312 | ||
267 | assert(pointer->cursor_theme = wl_cursor_theme_load(NULL, 16, bar->shm)); | 313 | int max_scale = 1; |
314 | struct swaybar_output *output; | ||
315 | wl_list_for_each(output, &bar->outputs, link) { | ||
316 | if (output->scale > max_scale) { | ||
317 | max_scale = output->scale; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | pointer->cursor_theme = wl_cursor_theme_load( | ||
322 | NULL, 24 * max_scale, bar->shm); | ||
323 | assert(pointer->cursor_theme); | ||
268 | struct wl_cursor *cursor; | 324 | struct wl_cursor *cursor; |
269 | assert(cursor = wl_cursor_theme_get_cursor( | 325 | cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); |
270 | pointer->cursor_theme, "left_ptr")); | 326 | assert(cursor); |
271 | pointer->cursor_image = cursor->images[0]; | 327 | pointer->cursor_image = cursor->images[0]; |
272 | assert(pointer->cursor_surface = | 328 | pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); |
273 | wl_compositor_create_surface(bar->compositor)); | 329 | assert(pointer->cursor_surface); |
274 | 330 | ||
275 | // TODO: we might not necessarily be meant to do all of the outputs | 331 | // TODO: we might not necessarily be meant to do all of the outputs |
276 | struct swaybar_output *output; | ||
277 | wl_list_for_each(output, &bar->outputs, link) { | 332 | wl_list_for_each(output, &bar->outputs, link) { |
278 | struct config_output *coutput; | 333 | struct config_output *coutput; |
279 | wl_list_for_each(coutput, &bar->config->outputs, link) { | 334 | wl_list_for_each(coutput, &bar->config->outputs, link) { |
@@ -281,8 +336,8 @@ void bar_setup(struct swaybar *bar, | |||
281 | continue; | 336 | continue; |
282 | } | 337 | } |
283 | output->name = strdup(coutput->name); | 338 | output->name = strdup(coutput->name); |
284 | assert(output->surface = wl_compositor_create_surface( | 339 | output->surface = wl_compositor_create_surface(bar->compositor); |
285 | bar->compositor)); | 340 | assert(output->surface); |
286 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( | 341 | output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( |
287 | bar->layer_shell, output->surface, output->output, | 342 | bar->layer_shell, output->surface, output->output, |
288 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); | 343 | ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); |
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 46459e24..ed134a01 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c | |||
@@ -203,6 +203,9 @@ void i3bar_block_send_click(struct status_line *status, | |||
203 | json_object_object_add(event_json, "button", json_object_new_int(button)); | 203 | json_object_object_add(event_json, "button", json_object_new_int(button)); |
204 | json_object_object_add(event_json, "x", json_object_new_int(x)); | 204 | json_object_object_add(event_json, "x", json_object_new_int(x)); |
205 | json_object_object_add(event_json, "y", json_object_new_int(y)); | 205 | json_object_object_add(event_json, "y", json_object_new_int(y)); |
206 | dprintf(status->write_fd, "%s\n", json_object_to_json_string(event_json)); | 206 | if (dprintf(status->write_fd, "%s\n", |
207 | json_object_to_json_string(event_json)) < 0) { | ||
208 | status_error(status, "[failed to write click event]"); | ||
209 | } | ||
207 | json_object_put(event_json); | 210 | json_object_put(event_json); |
208 | } | 211 | } |
diff --git a/swaybar/render.c b/swaybar/render.c index 6f3b0788..be58301d 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -14,55 +14,72 @@ | |||
14 | #include "swaybar/status_line.h" | 14 | #include "swaybar/status_line.h" |
15 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" | 15 | #include "wlr-layer-shell-unstable-v1-client-protocol.h" |
16 | 16 | ||
17 | static const int ws_horizontal_padding = 5; | 17 | static const int WS_HORIZONTAL_PADDING = 5; |
18 | static const double ws_vertical_padding = 1.5; | 18 | static const double WS_VERTICAL_PADDING = 1.5; |
19 | static const double border_width = 1; | 19 | static const double BORDER_WIDTH = 1; |
20 | 20 | ||
21 | static uint32_t render_status_line_error(cairo_t *cairo, | 21 | static uint32_t render_status_line_error(cairo_t *cairo, |
22 | struct swaybar_config *config, const char *error, | 22 | struct swaybar_output *output, struct swaybar_config *config, |
23 | double *x, uint32_t width, uint32_t height) { | 23 | const char *error, double *x, uint32_t surface_height) { |
24 | if (!error) { | 24 | if (!error) { |
25 | return 0; | 25 | return 0; |
26 | } | 26 | } |
27 | |||
28 | uint32_t height = surface_height * output->scale; | ||
29 | |||
27 | cairo_set_source_u32(cairo, 0xFF0000FF); | 30 | cairo_set_source_u32(cairo, 0xFF0000FF); |
28 | static const int margin = 3; | 31 | |
32 | int margin = 3 * output->scale; | ||
33 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | ||
34 | |||
29 | int text_width, text_height; | 35 | int text_width, text_height; |
30 | get_text_size(cairo, config->font, | 36 | get_text_size(cairo, config->font, |
31 | &text_width, &text_height, 1, false, "%s", error); | 37 | &text_width, &text_height, output->scale, false, "%s", error); |
38 | |||
32 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 39 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
33 | if (height < ideal_height) { | 40 | if (height < ideal_height) { |
34 | return ideal_height; | 41 | return ideal_height / output->scale; |
35 | } | 42 | } |
36 | *x -= text_width + margin; | 43 | *x -= text_width + margin; |
44 | |||
37 | double text_y = height / 2.0 - text_height / 2.0; | 45 | double text_y = height / 2.0 - text_height / 2.0; |
38 | cairo_move_to(cairo, *x, (int)floor(text_y)); | 46 | cairo_move_to(cairo, *x, (int)floor(text_y)); |
39 | pango_printf(cairo, config->font, 1, false, "%s", error); | 47 | pango_printf(cairo, config->font, output->scale, false, "%s", error); |
40 | *x -= margin; | 48 | *x -= margin; |
41 | return ideal_height; | 49 | return ideal_height / output->scale; |
42 | } | 50 | } |
43 | 51 | ||
44 | static uint32_t render_status_line_text(cairo_t *cairo, | 52 | static uint32_t render_status_line_text(cairo_t *cairo, |
45 | struct swaybar_config *config, const char *text, | 53 | struct swaybar_output *output, struct swaybar_config *config, |
46 | bool focused, double *x, uint32_t width, uint32_t height) { | 54 | const char *text, bool focused, double *x, uint32_t surface_height) { |
47 | if (!text) { | 55 | if (!text) { |
48 | return 0; | 56 | return 0; |
49 | } | 57 | } |
58 | |||
59 | uint32_t height = surface_height * output->scale; | ||
60 | |||
50 | cairo_set_source_u32(cairo, focused ? | 61 | cairo_set_source_u32(cairo, focused ? |
51 | config->colors.focused_statusline : config->colors.statusline); | 62 | config->colors.focused_statusline : config->colors.statusline); |
52 | static const int margin = 3; | 63 | |
53 | int text_width, text_height; | 64 | int text_width, text_height; |
54 | get_text_size(cairo, config->font, &text_width, &text_height, | 65 | get_text_size(cairo, config->font, &text_width, &text_height, |
55 | 1, config->pango_markup, "%s", text); | 66 | output->scale, config->pango_markup, "%s", text); |
67 | |||
68 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | ||
69 | int margin = 3 * output->scale; | ||
70 | |||
56 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 71 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
57 | if (height < ideal_height) { | 72 | if (height < ideal_height) { |
58 | return ideal_height; | 73 | return ideal_height / output->scale; |
59 | } | 74 | } |
75 | |||
60 | *x -= text_width + margin; | 76 | *x -= text_width + margin; |
61 | double text_y = height / 2.0 - text_height / 2.0; | 77 | double text_y = height / 2.0 - text_height / 2.0; |
62 | cairo_move_to(cairo, *x, (int)floor(text_y)); | 78 | cairo_move_to(cairo, *x, (int)floor(text_y)); |
63 | pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text); | 79 | pango_printf(cairo, config->font, output->scale, |
80 | config->pango_markup, "%s", text); | ||
64 | *x -= margin; | 81 | *x -= margin; |
65 | return ideal_height; | 82 | return ideal_height / output->scale; |
66 | } | 83 | } |
67 | 84 | ||
68 | static void render_sharp_line(cairo_t *cairo, uint32_t color, | 85 | static void render_sharp_line(cairo_t *cairo, uint32_t color, |
@@ -99,23 +116,29 @@ static void block_hotspot_callback(struct swaybar_output *output, | |||
99 | static uint32_t render_status_block(cairo_t *cairo, | 116 | static uint32_t render_status_block(cairo_t *cairo, |
100 | struct swaybar_config *config, struct swaybar_output *output, | 117 | struct swaybar_config *config, struct swaybar_output *output, |
101 | struct i3bar_block *block, double *x, | 118 | struct i3bar_block *block, double *x, |
102 | uint32_t height, bool focused, bool edge) { | 119 | uint32_t surface_height, bool focused, bool edge) { |
103 | static const int margin = 3; | ||
104 | if (!block->full_text || !*block->full_text) { | 120 | if (!block->full_text || !*block->full_text) { |
105 | return 0; | 121 | return 0; |
106 | } | 122 | } |
107 | 123 | ||
124 | uint32_t height = surface_height * output->scale; | ||
125 | |||
108 | int text_width, text_height; | 126 | int text_width, text_height; |
109 | get_text_size(cairo, config->font, &text_width, &text_height, | 127 | get_text_size(cairo, config->font, &text_width, &text_height, |
110 | 1, block->markup, "%s", block->full_text); | 128 | output->scale, block->markup, "%s", block->full_text); |
129 | |||
130 | int margin = 3 * output->scale; | ||
131 | int ws_vertical_padding = WS_VERTICAL_PADDING * 2; | ||
132 | |||
111 | int width = text_width; | 133 | int width = text_width; |
112 | if (width < block->min_width) { | 134 | if (width < block->min_width) { |
113 | width = block->min_width; | 135 | width = block->min_width; |
114 | } | 136 | } |
137 | |||
115 | double block_width = width; | 138 | double block_width = width; |
116 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 139 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; |
117 | if (height < ideal_height) { | 140 | if (height < ideal_height) { |
118 | return ideal_height; | 141 | return ideal_height / output->scale; |
119 | } | 142 | } |
120 | 143 | ||
121 | *x -= width; | 144 | *x -= width; |
@@ -133,10 +156,10 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
133 | if (config->sep_symbol) { | 156 | if (config->sep_symbol) { |
134 | int _height; | 157 | int _height; |
135 | get_text_size(cairo, config->font, &sep_width, &_height, | 158 | get_text_size(cairo, config->font, &sep_width, &_height, |
136 | 1, false, "%s", config->sep_symbol); | 159 | output->scale, false, "%s", config->sep_symbol); |
137 | uint32_t _ideal_height = _height + ws_vertical_padding * 2; | 160 | uint32_t _ideal_height = _height + ws_vertical_padding * 2; |
138 | if (height < _ideal_height) { | 161 | if ((uint32_t)_height < _ideal_height / output->scale) { |
139 | return _height; | 162 | return _height / output->scale; |
140 | } | 163 | } |
141 | if (sep_width > block->separator_block_width) { | 164 | if (sep_width > block->separator_block_width) { |
142 | block->separator_block_width = sep_width + margin * 2; | 165 | block->separator_block_width = sep_width + margin * 2; |
@@ -160,22 +183,26 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
160 | double pos = *x; | 183 | double pos = *x; |
161 | if (block->background) { | 184 | if (block->background) { |
162 | cairo_set_source_u32(cairo, block->background); | 185 | cairo_set_source_u32(cairo, block->background); |
163 | cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); | 186 | cairo_rectangle(cairo, pos - 0.5 * output->scale, |
187 | output->scale, block_width, height); | ||
164 | cairo_fill(cairo); | 188 | cairo_fill(cairo); |
165 | } | 189 | } |
166 | 190 | ||
167 | if (block->border && block->border_top > 0) { | 191 | if (block->border && block->border_top > 0) { |
168 | render_sharp_line(cairo, block->border, | 192 | render_sharp_line(cairo, block->border, |
169 | pos - 0.5, 1, block_width, block->border_top); | 193 | pos - 0.5 * output->scale, output->scale, |
194 | block_width, block->border_top); | ||
170 | } | 195 | } |
171 | if (block->border && block->border_bottom > 0) { | 196 | if (block->border && block->border_bottom > 0) { |
172 | render_sharp_line(cairo, block->border, | 197 | render_sharp_line(cairo, block->border, |
173 | pos - 0.5, height - 1 - block->border_bottom, | 198 | pos - 0.5 * output->scale, |
199 | height - output->scale - block->border_bottom, | ||
174 | block_width, block->border_bottom); | 200 | block_width, block->border_bottom); |
175 | } | 201 | } |
176 | if (block->border != 0 && block->border_left > 0) { | 202 | if (block->border != 0 && block->border_left > 0) { |
177 | render_sharp_line(cairo, block->border, | 203 | render_sharp_line(cairo, block->border, |
178 | pos - 0.5, 1, block->border_left, height); | 204 | pos - 0.5 * output->scale, output->scale, |
205 | block->border_left, height); | ||
179 | pos += block->border_left + margin; | 206 | pos += block->border_left + margin; |
180 | } | 207 | } |
181 | 208 | ||
@@ -190,13 +217,15 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
190 | cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); | 217 | cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); |
191 | uint32_t color = block->color ? *block->color : config->colors.statusline; | 218 | uint32_t color = block->color ? *block->color : config->colors.statusline; |
192 | cairo_set_source_u32(cairo, color); | 219 | cairo_set_source_u32(cairo, color); |
193 | pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); | 220 | pango_printf(cairo, config->font, output->scale, |
221 | block->markup, "%s", block->full_text); | ||
194 | pos += width; | 222 | pos += width; |
195 | 223 | ||
196 | if (block->border && block->border_right > 0) { | 224 | if (block->border && block->border_right > 0) { |
197 | pos += margin; | 225 | pos += margin; |
198 | render_sharp_line(cairo, block->border, | 226 | render_sharp_line(cairo, block->border, |
199 | pos - 0.5, 1, block->border_right, height); | 227 | pos - 0.5 * output->scale, output->scale, |
228 | block->border_right, height); | ||
200 | pos += block->border_right; | 229 | pos += block->border_right; |
201 | } | 230 | } |
202 | 231 | ||
@@ -209,7 +238,7 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
209 | if (config->sep_symbol) { | 238 | if (config->sep_symbol) { |
210 | offset = pos + (block->separator_block_width - sep_width) / 2; | 239 | offset = pos + (block->separator_block_width - sep_width) / 2; |
211 | cairo_move_to(cairo, offset, margin); | 240 | cairo_move_to(cairo, offset, margin); |
212 | pango_printf(cairo, config->font, 1, false, | 241 | pango_printf(cairo, config->font, output->scale, false, |
213 | "%s", config->sep_symbol); | 242 | "%s", config->sep_symbol); |
214 | } else { | 243 | } else { |
215 | cairo_set_line_width(cairo, 1); | 244 | cairo_set_line_width(cairo, 1); |
@@ -220,19 +249,19 @@ static uint32_t render_status_block(cairo_t *cairo, | |||
220 | cairo_stroke(cairo); | 249 | cairo_stroke(cairo); |
221 | } | 250 | } |
222 | } | 251 | } |
223 | return ideal_height; | 252 | return ideal_height / output->scale; |
224 | } | 253 | } |
225 | 254 | ||
226 | static uint32_t render_status_line_i3bar(cairo_t *cairo, | 255 | static uint32_t render_status_line_i3bar(cairo_t *cairo, |
227 | struct swaybar_config *config, struct swaybar_output *output, | 256 | struct swaybar_config *config, struct swaybar_output *output, |
228 | struct status_line *status, bool focused, | 257 | struct status_line *status, bool focused, |
229 | double *x, uint32_t width, uint32_t height) { | 258 | double *x, uint32_t surface_height) { |
230 | uint32_t max_height = 0; | 259 | uint32_t max_height = 0; |
231 | bool edge = true; | 260 | bool edge = true; |
232 | struct i3bar_block *block; | 261 | struct i3bar_block *block; |
233 | wl_list_for_each(block, &status->blocks, link) { | 262 | wl_list_for_each(block, &status->blocks, link) { |
234 | uint32_t h = render_status_block(cairo, config, output, | 263 | uint32_t h = render_status_block(cairo, config, output, |
235 | block, x, height, focused, edge); | 264 | block, x, surface_height, focused, edge); |
236 | max_height = h > max_height ? h : max_height; | 265 | max_height = h > max_height ? h : max_height; |
237 | edge = false; | 266 | edge = false; |
238 | } | 267 | } |
@@ -242,17 +271,17 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, | |||
242 | static uint32_t render_status_line(cairo_t *cairo, | 271 | static uint32_t render_status_line(cairo_t *cairo, |
243 | struct swaybar_config *config, struct swaybar_output *output, | 272 | struct swaybar_config *config, struct swaybar_output *output, |
244 | struct status_line *status, bool focused, | 273 | struct status_line *status, bool focused, |
245 | double *x, uint32_t width, uint32_t height) { | 274 | double *x, uint32_t surface_height) { |
246 | switch (status->protocol) { | 275 | switch (status->protocol) { |
247 | case PROTOCOL_ERROR: | 276 | case PROTOCOL_ERROR: |
248 | return render_status_line_error(cairo, | 277 | return render_status_line_error(cairo, output, config, |
249 | config, status->text, x, width, height); | 278 | status->text, x, surface_height); |
250 | case PROTOCOL_TEXT: | 279 | case PROTOCOL_TEXT: |
251 | return render_status_line_text(cairo, | 280 | return render_status_line_text(cairo, output, config, |
252 | config, status->text, focused, x, width, height); | 281 | status->text, focused, x, surface_height); |
253 | case PROTOCOL_I3BAR: | 282 | case PROTOCOL_I3BAR: |
254 | return render_status_line_i3bar(cairo, config, output, status, | 283 | return render_status_line_i3bar(cairo, config, output, |
255 | focused, x, width, height); | 284 | status, focused, x, surface_height); |
256 | case PROTOCOL_UNDEF: | 285 | case PROTOCOL_UNDEF: |
257 | return 0; | 286 | return 0; |
258 | } | 287 | } |
@@ -260,15 +289,23 @@ static uint32_t render_status_line(cairo_t *cairo, | |||
260 | } | 289 | } |
261 | 290 | ||
262 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 291 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, |
263 | struct swaybar_config *config, const char *mode, double x, | 292 | struct swaybar_output *output, struct swaybar_config *config, |
264 | uint32_t height) { | 293 | const char *mode, double x, uint32_t surface_height) { |
294 | |||
295 | uint32_t height = surface_height * output->scale; | ||
296 | |||
265 | int text_width, text_height; | 297 | int text_width, text_height; |
266 | get_text_size(cairo, config->font, &text_width, &text_height, | 298 | get_text_size(cairo, config->font, &text_width, &text_height, |
267 | 1, true, "%s", mode); | 299 | output->scale, true, "%s", mode); |
300 | |||
301 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | ||
302 | int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; | ||
303 | int border_width = BORDER_WIDTH * output->scale; | ||
304 | |||
268 | uint32_t ideal_height = text_height + ws_vertical_padding * 2 | 305 | uint32_t ideal_height = text_height + ws_vertical_padding * 2 |
269 | + border_width * 2; | 306 | + border_width * 2; |
270 | if (height < ideal_height) { | 307 | if (height < ideal_height) { |
271 | return ideal_height; | 308 | return ideal_height / output->scale; |
272 | } | 309 | } |
273 | uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; | 310 | uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; |
274 | 311 | ||
@@ -289,8 +326,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, | |||
289 | double text_y = height / 2.0 - text_height / 2.0; | 326 | double text_y = height / 2.0 - text_height / 2.0; |
290 | cairo_set_source_u32(cairo, config->colors.binding_mode.text); | 327 | cairo_set_source_u32(cairo, config->colors.binding_mode.text); |
291 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); | 328 | cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); |
292 | pango_printf(cairo, config->font, 1, true, "%s", mode); | 329 | pango_printf(cairo, config->font, output->scale, true, "%s", mode); |
293 | return ideal_height; | 330 | return ideal_height / output->scale; |
294 | } | 331 | } |
295 | 332 | ||
296 | static const char *strip_workspace_number(const char *ws_name) { | 333 | static const char *strip_workspace_number(const char *ws_name) { |
@@ -313,7 +350,7 @@ static void workspace_hotspot_callback(struct swaybar_output *output, | |||
313 | 350 | ||
314 | static uint32_t render_workspace_button(cairo_t *cairo, | 351 | static uint32_t render_workspace_button(cairo_t *cairo, |
315 | struct swaybar_output *output, struct swaybar_config *config, | 352 | struct swaybar_output *output, struct swaybar_config *config, |
316 | struct swaybar_workspace *ws, double *x, uint32_t height) { | 353 | struct swaybar_workspace *ws, double *x, uint32_t surface_height) { |
317 | const char *name = ws->name; | 354 | const char *name = ws->name; |
318 | if (config->strip_workspace_numbers) { | 355 | if (config->strip_workspace_numbers) { |
319 | name = strip_workspace_number(ws->name); | 356 | name = strip_workspace_number(ws->name); |
@@ -330,14 +367,22 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
330 | box_colors = config->colors.inactive_workspace; | 367 | box_colors = config->colors.inactive_workspace; |
331 | } | 368 | } |
332 | 369 | ||
370 | uint32_t height = surface_height * output->scale; | ||
371 | |||
333 | int text_width, text_height; | 372 | int text_width, text_height; |
334 | get_text_size(cairo, config->font, &text_width, &text_height, | 373 | get_text_size(cairo, config->font, &text_width, &text_height, |
335 | 1, true, "%s", name); | 374 | output->scale, true, "%s", name); |
375 | |||
376 | int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | ||
377 | int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; | ||
378 | int border_width = BORDER_WIDTH * output->scale; | ||
379 | |||
336 | uint32_t ideal_height = ws_vertical_padding * 2 + text_height | 380 | uint32_t ideal_height = ws_vertical_padding * 2 + text_height |
337 | + border_width * 2; | 381 | + border_width * 2; |
338 | if (height < ideal_height) { | 382 | if (height < ideal_height) { |
339 | return ideal_height; | 383 | return ideal_height / output->scale; |
340 | } | 384 | } |
385 | |||
341 | uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; | 386 | uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; |
342 | 387 | ||
343 | cairo_set_source_u32(cairo, box_colors.background); | 388 | cairo_set_source_u32(cairo, box_colors.background); |
@@ -357,7 +402,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
357 | double text_y = height / 2.0 - text_height / 2.0; | 402 | double text_y = height / 2.0 - text_height / 2.0; |
358 | cairo_set_source_u32(cairo, box_colors.text); | 403 | cairo_set_source_u32(cairo, box_colors.text); |
359 | cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); | 404 | cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); |
360 | pango_printf(cairo, config->font, 1, true, "%s", name); | 405 | pango_printf(cairo, config->font, output->scale, true, "%s", name); |
361 | 406 | ||
362 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | 407 | struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); |
363 | hotspot->x = *x; | 408 | hotspot->x = *x; |
@@ -370,7 +415,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, | |||
370 | wl_list_insert(&output->hotspots, &hotspot->link); | 415 | wl_list_insert(&output->hotspots, &hotspot->link); |
371 | 416 | ||
372 | *x += width; | 417 | *x += width; |
373 | return height; | 418 | return height / output->scale; |
374 | } | 419 | } |
375 | 420 | ||
376 | static uint32_t render_to_cairo(cairo_t *cairo, | 421 | static uint32_t render_to_cairo(cairo_t *cairo, |
@@ -394,7 +439,13 @@ static uint32_t render_to_cairo(cairo_t *cairo, | |||
394 | * height is too tall, the render function should adapt its drawing to | 439 | * height is too tall, the render function should adapt its drawing to |
395 | * utilize the available space. | 440 | * utilize the available space. |
396 | */ | 441 | */ |
397 | double x = 0; | 442 | double x = output->width * output->scale; |
443 | if (bar->status) { | ||
444 | uint32_t h = render_status_line(cairo, config, output, | ||
445 | bar->status, output->focused, &x, output->height); | ||
446 | max_height = h > max_height ? h : max_height; | ||
447 | } | ||
448 | x = 0; | ||
398 | if (config->workspace_buttons) { | 449 | if (config->workspace_buttons) { |
399 | struct swaybar_workspace *ws; | 450 | struct swaybar_workspace *ws; |
400 | wl_list_for_each_reverse(ws, &output->workspaces, link) { | 451 | wl_list_for_each_reverse(ws, &output->workspaces, link) { |
@@ -404,14 +455,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, | |||
404 | } | 455 | } |
405 | } | 456 | } |
406 | if (config->binding_mode_indicator && config->mode) { | 457 | if (config->binding_mode_indicator && config->mode) { |
407 | uint32_t h = render_binding_mode_indicator( | 458 | uint32_t h = render_binding_mode_indicator(cairo, |
408 | cairo, config, config->mode, x, output->height); | 459 | output, config, config->mode, x, output->height); |
409 | max_height = h > max_height ? h : max_height; | ||
410 | } | ||
411 | x = output->width; | ||
412 | if (bar->status) { | ||
413 | uint32_t h = render_status_line(cairo, config, output, bar->status, | ||
414 | output->focused, &x, output->width, output->height); | ||
415 | max_height = h > max_height ? h : max_height; | 460 | max_height = h > max_height ? h : max_height; |
416 | } | 461 | } |
417 | 462 | ||
@@ -451,7 +496,9 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
451 | } else { | 496 | } else { |
452 | // Replay recording into shm and send it off | 497 | // Replay recording into shm and send it off |
453 | output->current_buffer = get_next_buffer(bar->shm, | 498 | output->current_buffer = get_next_buffer(bar->shm, |
454 | output->buffers, output->width, output->height); | 499 | output->buffers, |
500 | output->width * output->scale, | ||
501 | output->height * output->scale); | ||
455 | cairo_t *shm = output->current_buffer->cairo; | 502 | cairo_t *shm = output->current_buffer->cairo; |
456 | 503 | ||
457 | cairo_save(shm); | 504 | cairo_save(shm); |
@@ -462,9 +509,11 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
462 | cairo_set_source_surface(shm, recorder, 0.0, 0.0); | 509 | cairo_set_source_surface(shm, recorder, 0.0, 0.0); |
463 | cairo_paint(shm); | 510 | cairo_paint(shm); |
464 | 511 | ||
512 | wl_surface_set_buffer_scale(output->surface, output->scale); | ||
465 | wl_surface_attach(output->surface, | 513 | wl_surface_attach(output->surface, |
466 | output->current_buffer->buffer, 0, 0); | 514 | output->current_buffer->buffer, 0, 0); |
467 | wl_surface_damage(output->surface, 0, 0, output->width, output->height); | 515 | wl_surface_damage(output->surface, 0, 0, |
516 | output->width, output->height); | ||
468 | wl_surface_commit(output->surface); | 517 | wl_surface_commit(output->surface); |
469 | wl_display_roundtrip(bar->display); | 518 | wl_display_roundtrip(bar->display); |
470 | } | 519 | } |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index cc7e217f..8afe4707 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -59,7 +59,11 @@ bool status_handle_readable(struct status_line *status) { | |||
59 | wlr_log(L_DEBUG, "Enabled click events."); | 59 | wlr_log(L_DEBUG, "Enabled click events."); |
60 | status->i3bar_state.click_events = true; | 60 | status->i3bar_state.click_events = true; |
61 | const char *events_array = "[\n"; | 61 | const char *events_array = "[\n"; |
62 | write(status->write_fd, events_array, strlen(events_array)); | 62 | ssize_t len = strlen(events_array); |
63 | if (write(status->write_fd, events_array, len) != len) { | ||
64 | status_error(status, | ||
65 | "[failed to write to status command]"); | ||
66 | } | ||
63 | } | 67 | } |
64 | json_object_put(proto); | 68 | json_object_put(proto); |
65 | } | 69 | } |
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"); |