diff options
author | Alexander Orzechowski <alex@ozal.ski> | 2023-11-21 19:51:57 -0500 |
---|---|---|
committer | Kirill Primak <vyivel@eclair.cafe> | 2024-01-18 18:36:54 +0300 |
commit | 6d7b1321db54155cf78305dbafdcfc7de9b78415 (patch) | |
tree | acf9f02681b1d5a40416be5f4151641920176a93 /sway/tree/container.c | |
parent | scene_graph: Port layer_shell (diff) | |
download | sway-6d7b1321db54155cf78305dbafdcfc7de9b78415.tar.gz sway-6d7b1321db54155cf78305dbafdcfc7de9b78415.tar.zst sway-6d7b1321db54155cf78305dbafdcfc7de9b78415.zip |
scene_graph: Port container server side decorations
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 545 |
1 files changed, 333 insertions, 212 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 8fca6a12..4aae4d32 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -8,15 +8,13 @@ | |||
8 | #include <wlr/types/wlr_output_layout.h> | 8 | #include <wlr/types/wlr_output_layout.h> |
9 | #include <wlr/types/wlr_subcompositor.h> | 9 | #include <wlr/types/wlr_subcompositor.h> |
10 | #include "linux-dmabuf-unstable-v1-protocol.h" | 10 | #include "linux-dmabuf-unstable-v1-protocol.h" |
11 | #include "cairo_util.h" | ||
12 | #include "pango.h" | ||
13 | #include "sway/config.h" | 11 | #include "sway/config.h" |
14 | #include "sway/desktop.h" | ||
15 | #include "sway/desktop/transaction.h" | 12 | #include "sway/desktop/transaction.h" |
16 | #include "sway/input/input-manager.h" | 13 | #include "sway/input/input-manager.h" |
17 | #include "sway/input/seat.h" | 14 | #include "sway/input/seat.h" |
18 | #include "sway/ipc-server.h" | 15 | #include "sway/ipc-server.h" |
19 | #include "sway/scene_descriptor.h" | 16 | #include "sway/scene_descriptor.h" |
17 | #include "sway/sway_text_node.h" | ||
20 | #include "sway/output.h" | 18 | #include "sway/output.h" |
21 | #include "sway/server.h" | 19 | #include "sway/server.h" |
22 | #include "sway/surface.h" | 20 | #include "sway/surface.h" |
@@ -120,9 +118,328 @@ struct sway_container *container_create(struct sway_view *view) { | |||
120 | wl_signal_init(&c->events.destroy); | 118 | wl_signal_init(&c->events.destroy); |
121 | wl_signal_emit_mutable(&root->events.new_node, &c->node); | 119 | wl_signal_emit_mutable(&root->events.new_node, &c->node); |
122 | 120 | ||
121 | container_update(c); | ||
122 | |||
123 | return c; | 123 | return c; |
124 | } | 124 | } |
125 | 125 | ||
126 | static bool container_is_focused(struct sway_container *con, void *data) { | ||
127 | return con->current.focused; | ||
128 | } | ||
129 | |||
130 | static bool container_has_focused_child(struct sway_container *con) { | ||
131 | return container_find_child(con, container_is_focused, NULL); | ||
132 | } | ||
133 | |||
134 | static bool container_is_current_parent_focused(struct sway_container *con) { | ||
135 | if (con->current.parent) { | ||
136 | struct sway_container *parent = con->current.parent; | ||
137 | return parent->current.focused || container_is_current_parent_focused(parent); | ||
138 | } else if (con->current.workspace) { | ||
139 | struct sway_workspace *ws = con->current.workspace; | ||
140 | return ws->current.focused; | ||
141 | } | ||
142 | |||
143 | return false; | ||
144 | } | ||
145 | |||
146 | static struct border_colors *container_get_current_colors( | ||
147 | struct sway_container *con) { | ||
148 | struct border_colors *colors; | ||
149 | |||
150 | bool urgent = con->view ? | ||
151 | view_is_urgent(con->view) : container_has_urgent_child(con); | ||
152 | struct sway_container *active_child; | ||
153 | |||
154 | if (con->current.parent) { | ||
155 | active_child = con->current.parent->current.focused_inactive_child; | ||
156 | } else if (con->current.workspace) { | ||
157 | active_child = con->current.workspace->current.focused_inactive_child; | ||
158 | } else { | ||
159 | active_child = NULL; | ||
160 | } | ||
161 | |||
162 | if (urgent) { | ||
163 | colors = &config->border_colors.urgent; | ||
164 | } else if (con->current.focused || container_is_current_parent_focused(con)) { | ||
165 | colors = &config->border_colors.focused; | ||
166 | } else if (config->has_focused_tab_title && container_has_focused_child(con)) { | ||
167 | colors = &config->border_colors.focused_tab_title; | ||
168 | } else if (con == active_child) { | ||
169 | colors = &config->border_colors.focused_inactive; | ||
170 | } else { | ||
171 | colors = &config->border_colors.unfocused; | ||
172 | } | ||
173 | |||
174 | return colors; | ||
175 | } | ||
176 | |||
177 | static bool container_is_current_floating(struct sway_container *container) { | ||
178 | if (!container->current.parent && container->current.workspace && | ||
179 | list_find(container->current.workspace->floating, container) != -1) { | ||
180 | return true; | ||
181 | } | ||
182 | if (container->scratchpad) { | ||
183 | return true; | ||
184 | } | ||
185 | return false; | ||
186 | } | ||
187 | |||
188 | // scene rect wants premultiplied colors | ||
189 | static void scene_rect_set_color(struct wlr_scene_rect *rect, | ||
190 | const float color[4], float opacity) { | ||
191 | const float premultiplied[] = { | ||
192 | color[0] * color[3] * opacity, | ||
193 | color[1] * color[3] * opacity, | ||
194 | color[2] * color[3] * opacity, | ||
195 | color[3] * opacity, | ||
196 | }; | ||
197 | |||
198 | wlr_scene_rect_set_color(rect, premultiplied); | ||
199 | } | ||
200 | |||
201 | void container_update(struct sway_container *con) { | ||
202 | struct border_colors *colors = container_get_current_colors(con); | ||
203 | list_t *siblings = NULL; | ||
204 | enum sway_container_layout layout = L_NONE; | ||
205 | float alpha = con->alpha; | ||
206 | |||
207 | if (con->current.parent) { | ||
208 | siblings = con->current.parent->current.children; | ||
209 | layout = con->current.parent->current.layout; | ||
210 | } else if (con->current.workspace) { | ||
211 | siblings = con->current.workspace->current.tiling; | ||
212 | layout = con->current.workspace->current.layout; | ||
213 | } | ||
214 | |||
215 | float bottom[4], right[4]; | ||
216 | memcpy(bottom, colors->child_border, sizeof(bottom)); | ||
217 | memcpy(right, colors->child_border, sizeof(right)); | ||
218 | |||
219 | if (!container_is_current_floating(con) && siblings && siblings->length == 1) { | ||
220 | if (layout == L_HORIZ) { | ||
221 | memcpy(right, colors->indicator, sizeof(right)); | ||
222 | } else if (layout == L_VERT) { | ||
223 | memcpy(bottom, colors->indicator, sizeof(bottom)); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | struct wlr_scene_node *node; | ||
228 | wl_list_for_each(node, &con->title_bar.border->children, link) { | ||
229 | struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | ||
230 | scene_rect_set_color(rect, colors->border, alpha); | ||
231 | } | ||
232 | |||
233 | wl_list_for_each(node, &con->title_bar.background->children, link) { | ||
234 | struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | ||
235 | scene_rect_set_color(rect, colors->background, alpha); | ||
236 | } | ||
237 | |||
238 | if (con->view) { | ||
239 | scene_rect_set_color(con->border.top, colors->child_border, alpha); | ||
240 | scene_rect_set_color(con->border.bottom, bottom, alpha); | ||
241 | scene_rect_set_color(con->border.left, colors->child_border, alpha); | ||
242 | scene_rect_set_color(con->border.right, right, alpha); | ||
243 | } | ||
244 | |||
245 | if (con->title_bar.title_text) { | ||
246 | sway_text_node_set_color(con->title_bar.title_text, colors->text); | ||
247 | sway_text_node_set_background(con->title_bar.title_text, colors->background); | ||
248 | } | ||
249 | |||
250 | if (con->title_bar.marks_text) { | ||
251 | sway_text_node_set_color(con->title_bar.marks_text, colors->text); | ||
252 | sway_text_node_set_background(con->title_bar.marks_text, colors->background); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | void container_update_itself_and_parents(struct sway_container *con) { | ||
257 | container_update(con); | ||
258 | |||
259 | if (con->current.parent) { | ||
260 | container_update_itself_and_parents(con->current.parent); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static void update_rect_list(struct wlr_scene_tree *tree, pixman_region32_t *region) { | ||
265 | int len; | ||
266 | const pixman_box32_t *rects = pixman_region32_rectangles(region, &len); | ||
267 | |||
268 | wlr_scene_node_set_enabled(&tree->node, len > 0); | ||
269 | if (len == 0) { | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | int i = 0; | ||
274 | struct wlr_scene_node *node; | ||
275 | wl_list_for_each(node, &tree->children, link) { | ||
276 | struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); | ||
277 | wlr_scene_node_set_enabled(&rect->node, i < len); | ||
278 | |||
279 | if (i < len) { | ||
280 | const pixman_box32_t *box = &rects[i++]; | ||
281 | wlr_scene_node_set_position(&rect->node, box->x1, box->y1); | ||
282 | wlr_scene_rect_set_size(rect, box->x2 - box->x1, box->y2 - box->y1); | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | void container_arrange_title_bar(struct sway_container *con) { | ||
288 | enum alignment title_align = config->title_align; | ||
289 | int marks_buffer_width = 0; | ||
290 | int width = con->title_width; | ||
291 | int height = container_titlebar_height(); | ||
292 | |||
293 | pixman_region32_t text_area; | ||
294 | pixman_region32_init(&text_area); | ||
295 | |||
296 | if (con->title_bar.marks_text) { | ||
297 | struct sway_text_node *node = con->title_bar.marks_text; | ||
298 | marks_buffer_width = node->width; | ||
299 | |||
300 | int h_padding; | ||
301 | if (title_align == ALIGN_RIGHT) { | ||
302 | h_padding = config->titlebar_h_padding; | ||
303 | } else { | ||
304 | h_padding = width - config->titlebar_h_padding - marks_buffer_width; | ||
305 | } | ||
306 | |||
307 | h_padding = MAX(h_padding, 0); | ||
308 | |||
309 | int alloc_width = MIN((int)node->width, | ||
310 | width - h_padding - config->titlebar_h_padding); | ||
311 | sway_text_node_set_max_width(node, alloc_width); | ||
312 | wlr_scene_node_set_position(node->node, | ||
313 | h_padding, (height - node->height) >> 1); | ||
314 | |||
315 | pixman_region32_union_rect(&text_area, &text_area, | ||
316 | node->node->x, node->node->y, alloc_width, node->height); | ||
317 | } | ||
318 | |||
319 | if (con->title_bar.title_text) { | ||
320 | struct sway_text_node *node = con->title_bar.title_text; | ||
321 | |||
322 | int h_padding; | ||
323 | if (title_align == ALIGN_RIGHT) { | ||
324 | h_padding = width - config->titlebar_h_padding - node->width; | ||
325 | } else if (title_align == ALIGN_CENTER) { | ||
326 | h_padding = ((int)width - marks_buffer_width - node->width) >> 1; | ||
327 | } else { | ||
328 | h_padding = config->titlebar_h_padding; | ||
329 | } | ||
330 | |||
331 | h_padding = MAX(h_padding, 0); | ||
332 | |||
333 | int alloc_width = MIN((int) node->width, | ||
334 | width - h_padding - config->titlebar_h_padding); | ||
335 | sway_text_node_set_max_width(node, alloc_width); | ||
336 | wlr_scene_node_set_position(node->node, | ||
337 | h_padding, (height - node->height) >> 1); | ||
338 | |||
339 | pixman_region32_union_rect(&text_area, &text_area, | ||
340 | node->node->x, node->node->y, alloc_width, node->height); | ||
341 | } | ||
342 | |||
343 | // silence pixman errors | ||
344 | if (width <= 0 || height <= 0) { | ||
345 | pixman_region32_fini(&text_area); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | pixman_region32_t background, border; | ||
350 | |||
351 | int thickness = config->titlebar_border_thickness; | ||
352 | pixman_region32_init_rect(&background, | ||
353 | thickness, thickness, | ||
354 | width - thickness * 2, height - thickness * 2); | ||
355 | pixman_region32_init_rect(&border, 0, 0, width, height); | ||
356 | pixman_region32_subtract(&border, &border, &background); | ||
357 | |||
358 | pixman_region32_subtract(&background, &background, &text_area); | ||
359 | pixman_region32_fini(&text_area); | ||
360 | |||
361 | update_rect_list(con->title_bar.background, &background); | ||
362 | pixman_region32_fini(&background); | ||
363 | |||
364 | update_rect_list(con->title_bar.border, &border); | ||
365 | pixman_region32_fini(&border); | ||
366 | |||
367 | container_update(con); | ||
368 | } | ||
369 | |||
370 | void container_update_marks(struct sway_container *con) { | ||
371 | char *buffer = NULL; | ||
372 | |||
373 | if (config->show_marks && con->marks->length) { | ||
374 | size_t len = 0; | ||
375 | for (int i = 0; i < con->marks->length; ++i) { | ||
376 | char *mark = con->marks->items[i]; | ||
377 | if (mark[0] != '_') { | ||
378 | len += strlen(mark) + 2; | ||
379 | } | ||
380 | } | ||
381 | buffer = calloc(len + 1, 1); | ||
382 | char *part = malloc(len + 1); | ||
383 | |||
384 | if (!sway_assert(buffer && part, "Unable to allocate memory")) { | ||
385 | free(buffer); | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | for (int i = 0; i < con->marks->length; ++i) { | ||
390 | char *mark = con->marks->items[i]; | ||
391 | if (mark[0] != '_') { | ||
392 | snprintf(part, len + 1, "[%s]", mark); | ||
393 | strcat(buffer, part); | ||
394 | } | ||
395 | } | ||
396 | free(part); | ||
397 | } | ||
398 | |||
399 | if (!buffer) { | ||
400 | if (con->title_bar.marks_text) { | ||
401 | wlr_scene_node_destroy(con->title_bar.marks_text->node); | ||
402 | con->title_bar.marks_text = NULL; | ||
403 | } | ||
404 | } else if (!con->title_bar.marks_text) { | ||
405 | struct border_colors *colors = container_get_current_colors(con); | ||
406 | |||
407 | con->title_bar.marks_text = sway_text_node_create(con->title_bar.tree, | ||
408 | buffer, colors->text, false); | ||
409 | } else { | ||
410 | sway_text_node_set_text(con->title_bar.marks_text, buffer); | ||
411 | } | ||
412 | |||
413 | container_arrange_title_bar(con); | ||
414 | free(buffer); | ||
415 | } | ||
416 | |||
417 | void container_update_title_bar(struct sway_container *con) { | ||
418 | if (!con->formatted_title) { | ||
419 | return; | ||
420 | } | ||
421 | |||
422 | struct border_colors *colors = container_get_current_colors(con); | ||
423 | |||
424 | if (con->title_bar.title_text) { | ||
425 | wlr_scene_node_destroy(con->title_bar.title_text->node); | ||
426 | con->title_bar.title_text = NULL; | ||
427 | } | ||
428 | |||
429 | con->title_bar.title_text = sway_text_node_create(con->title_bar.tree, | ||
430 | con->formatted_title, colors->text, config->pango_markup); | ||
431 | |||
432 | // we always have to remake these text buffers completely for text font | ||
433 | // changes etc... | ||
434 | if (con->title_bar.marks_text) { | ||
435 | wlr_scene_node_destroy(con->title_bar.marks_text->node); | ||
436 | con->title_bar.marks_text = NULL; | ||
437 | } | ||
438 | |||
439 | container_update_marks(con); | ||
440 | container_arrange_title_bar(con); | ||
441 | } | ||
442 | |||
126 | void container_destroy(struct sway_container *con) { | 443 | void container_destroy(struct sway_container *con) { |
127 | if (!sway_assert(con->node.destroying, | 444 | if (!sway_assert(con->node.destroying, |
128 | "Tried to free container which wasn't marked as destroying")) { | 445 | "Tried to free container which wasn't marked as destroying")) { |
@@ -134,21 +451,11 @@ void container_destroy(struct sway_container *con) { | |||
134 | } | 451 | } |
135 | free(con->title); | 452 | free(con->title); |
136 | free(con->formatted_title); | 453 | free(con->formatted_title); |
137 | wlr_texture_destroy(con->title_focused); | ||
138 | wlr_texture_destroy(con->title_focused_inactive); | ||
139 | wlr_texture_destroy(con->title_unfocused); | ||
140 | wlr_texture_destroy(con->title_urgent); | ||
141 | wlr_texture_destroy(con->title_focused_tab_title); | ||
142 | list_free(con->pending.children); | 454 | list_free(con->pending.children); |
143 | list_free(con->current.children); | 455 | list_free(con->current.children); |
144 | list_free(con->outputs); | 456 | list_free(con->outputs); |
145 | 457 | ||
146 | list_free_items_and_destroy(con->marks); | 458 | list_free_items_and_destroy(con->marks); |
147 | wlr_texture_destroy(con->marks_focused); | ||
148 | wlr_texture_destroy(con->marks_focused_inactive); | ||
149 | wlr_texture_destroy(con->marks_unfocused); | ||
150 | wlr_texture_destroy(con->marks_urgent); | ||
151 | wlr_texture_destroy(con->marks_focused_tab_title); | ||
152 | 459 | ||
153 | if (con->view && con->view->container == con) { | 460 | if (con->view && con->view->container == con) { |
154 | con->view->container = NULL; | 461 | con->view->container = NULL; |
@@ -308,108 +615,6 @@ struct sway_output *container_get_effective_output(struct sway_container *con) { | |||
308 | return con->outputs->items[con->outputs->length - 1]; | 615 | return con->outputs->items[con->outputs->length - 1]; |
309 | } | 616 | } |
310 | 617 | ||
311 | static void render_titlebar_text_texture(struct sway_output *output, | ||
312 | struct sway_container *con, struct wlr_texture **texture, | ||
313 | struct border_colors *class, bool pango_markup, char *text) { | ||
314 | double scale = output->wlr_output->scale; | ||
315 | int width = 0; | ||
316 | int height = config->font_height * scale; | ||
317 | int baseline; | ||
318 | |||
319 | // We must use a non-nil cairo_t for cairo_set_font_options to work. | ||
320 | // Therefore, we cannot use cairo_create(NULL). | ||
321 | cairo_surface_t *dummy_surface = cairo_image_surface_create( | ||
322 | CAIRO_FORMAT_ARGB32, 0, 0); | ||
323 | cairo_t *c = cairo_create(dummy_surface); | ||
324 | cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST); | ||
325 | cairo_font_options_t *fo = cairo_font_options_create(); | ||
326 | if (output->wlr_output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { | ||
327 | cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); | ||
328 | } else { | ||
329 | cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | ||
330 | cairo_font_options_set_subpixel_order(fo, | ||
331 | to_cairo_subpixel_order(output->wlr_output->subpixel)); | ||
332 | } | ||
333 | cairo_set_font_options(c, fo); | ||
334 | get_text_size(c, config->font_description, &width, NULL, &baseline, scale, | ||
335 | config->pango_markup, "%s", text); | ||
336 | cairo_surface_destroy(dummy_surface); | ||
337 | cairo_destroy(c); | ||
338 | |||
339 | if (width == 0 || height == 0) { | ||
340 | return; | ||
341 | } | ||
342 | |||
343 | if (height > config->font_height * scale) { | ||
344 | height = config->font_height * scale; | ||
345 | } | ||
346 | |||
347 | cairo_surface_t *surface = cairo_image_surface_create( | ||
348 | CAIRO_FORMAT_ARGB32, width, height); | ||
349 | cairo_status_t status = cairo_surface_status(surface); | ||
350 | if (status != CAIRO_STATUS_SUCCESS) { | ||
351 | sway_log(SWAY_ERROR, "cairo_image_surface_create failed: %s", | ||
352 | cairo_status_to_string(status)); | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | cairo_t *cairo = cairo_create(surface); | ||
357 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
358 | cairo_set_font_options(cairo, fo); | ||
359 | cairo_font_options_destroy(fo); | ||
360 | cairo_set_source_rgba(cairo, class->background[0], class->background[1], | ||
361 | class->background[2], class->background[3]); | ||
362 | cairo_paint(cairo); | ||
363 | PangoContext *pango = pango_cairo_create_context(cairo); | ||
364 | cairo_set_source_rgba(cairo, class->text[0], class->text[1], | ||
365 | class->text[2], class->text[3]); | ||
366 | cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); | ||
367 | |||
368 | render_text(cairo, config->font_description, scale, pango_markup, "%s", text); | ||
369 | |||
370 | cairo_surface_flush(surface); | ||
371 | unsigned char *data = cairo_image_surface_get_data(surface); | ||
372 | int stride = cairo_image_surface_get_stride(surface); | ||
373 | struct wlr_renderer *renderer = output->wlr_output->renderer; | ||
374 | *texture = wlr_texture_from_pixels( | ||
375 | renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); | ||
376 | cairo_surface_destroy(surface); | ||
377 | g_object_unref(pango); | ||
378 | cairo_destroy(cairo); | ||
379 | } | ||
380 | |||
381 | static void update_title_texture(struct sway_container *con, | ||
382 | struct wlr_texture **texture, struct border_colors *class) { | ||
383 | struct sway_output *output = container_get_effective_output(con); | ||
384 | if (!output) { | ||
385 | return; | ||
386 | } | ||
387 | if (*texture) { | ||
388 | wlr_texture_destroy(*texture); | ||
389 | *texture = NULL; | ||
390 | } | ||
391 | if (!con->formatted_title) { | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | render_titlebar_text_texture(output, con, texture, class, | ||
396 | config->pango_markup, con->formatted_title); | ||
397 | } | ||
398 | |||
399 | void container_update_title_textures(struct sway_container *container) { | ||
400 | update_title_texture(container, &container->title_focused, | ||
401 | &config->border_colors.focused); | ||
402 | update_title_texture(container, &container->title_focused_inactive, | ||
403 | &config->border_colors.focused_inactive); | ||
404 | update_title_texture(container, &container->title_unfocused, | ||
405 | &config->border_colors.unfocused); | ||
406 | update_title_texture(container, &container->title_urgent, | ||
407 | &config->border_colors.urgent); | ||
408 | update_title_texture(container, &container->title_focused_tab_title, | ||
409 | &config->border_colors.focused_tab_title); | ||
410 | container_damage_whole(container); | ||
411 | } | ||
412 | |||
413 | /** | 618 | /** |
414 | * Calculate and return the length of the tree representation. | 619 | * Calculate and return the length of the tree representation. |
415 | * An example tree representation is: V[Terminal, Firefox] | 620 | * An example tree representation is: V[Terminal, Firefox] |
@@ -475,7 +680,13 @@ void container_update_representation(struct sway_container *con) { | |||
475 | } | 680 | } |
476 | container_build_representation(con->pending.layout, con->pending.children, | 681 | container_build_representation(con->pending.layout, con->pending.children, |
477 | con->formatted_title); | 682 | con->formatted_title); |
478 | container_update_title_textures(con); | 683 | |
684 | if (con->title_bar.title_text) { | ||
685 | sway_text_node_set_text(con->title_bar.title_text, con->formatted_title); | ||
686 | container_arrange_title_bar(con); | ||
687 | } else { | ||
688 | container_update_title_bar(con); | ||
689 | } | ||
479 | } | 690 | } |
480 | if (con->pending.parent) { | 691 | if (con->pending.parent) { |
481 | container_update_representation(con->pending.parent); | 692 | container_update_representation(con->pending.parent); |
@@ -761,17 +972,6 @@ bool container_is_floating(struct sway_container *container) { | |||
761 | return false; | 972 | return false; |
762 | } | 973 | } |
763 | 974 | ||
764 | bool container_is_current_floating(struct sway_container *container) { | ||
765 | if (!container->current.parent && container->current.workspace && | ||
766 | list_find(container->current.workspace->floating, container) != -1) { | ||
767 | return true; | ||
768 | } | ||
769 | if (container->scratchpad) { | ||
770 | return true; | ||
771 | } | ||
772 | return false; | ||
773 | } | ||
774 | |||
775 | void container_get_box(struct sway_container *container, struct wlr_box *box) { | 975 | void container_get_box(struct sway_container *container, struct wlr_box *box) { |
776 | box->x = container->pending.x; | 976 | box->x = container->pending.x; |
777 | box->y = container->pending.y; | 977 | box->y = container->pending.y; |
@@ -1092,7 +1292,6 @@ void container_discover_outputs(struct sway_container *con) { | |||
1092 | .width = con->current.width, | 1292 | .width = con->current.width, |
1093 | .height = con->current.height, | 1293 | .height = con->current.height, |
1094 | }; | 1294 | }; |
1095 | struct sway_output *old_output = container_get_effective_output(con); | ||
1096 | 1295 | ||
1097 | for (int i = 0; i < root->outputs->length; ++i) { | 1296 | for (int i = 0; i < root->outputs->length; ++i) { |
1098 | struct sway_output *output = root->outputs->items[i]; | 1297 | struct sway_output *output = root->outputs->items[i]; |
@@ -1129,14 +1328,6 @@ void container_discover_outputs(struct sway_container *con) { | |||
1129 | list_del(con->outputs, index); | 1328 | list_del(con->outputs, index); |
1130 | } | 1329 | } |
1131 | } | 1330 | } |
1132 | struct sway_output *new_output = container_get_effective_output(con); | ||
1133 | double old_scale = old_output && old_output->enabled ? | ||
1134 | old_output->wlr_output->scale : -1; | ||
1135 | double new_scale = new_output ? new_output->wlr_output->scale : -1; | ||
1136 | if (old_scale != new_scale) { | ||
1137 | container_update_title_textures(con); | ||
1138 | container_update_marks_textures(con); | ||
1139 | } | ||
1140 | } | 1331 | } |
1141 | 1332 | ||
1142 | enum sway_container_layout container_parent_layout(struct sway_container *con) { | 1333 | enum sway_container_layout container_parent_layout(struct sway_container *con) { |
@@ -1149,14 +1340,6 @@ enum sway_container_layout container_parent_layout(struct sway_container *con) { | |||
1149 | return L_NONE; | 1340 | return L_NONE; |
1150 | } | 1341 | } |
1151 | 1342 | ||
1152 | enum sway_container_layout container_current_parent_layout( | ||
1153 | struct sway_container *con) { | ||
1154 | if (con->current.parent) { | ||
1155 | return con->current.parent->current.layout; | ||
1156 | } | ||
1157 | return con->current.workspace->current.layout; | ||
1158 | } | ||
1159 | |||
1160 | list_t *container_get_siblings(struct sway_container *container) { | 1343 | list_t *container_get_siblings(struct sway_container *container) { |
1161 | if (container->pending.parent) { | 1344 | if (container->pending.parent) { |
1162 | return container->pending.parent->pending.children; | 1345 | return container->pending.parent->pending.children; |
@@ -1174,13 +1357,6 @@ int container_sibling_index(struct sway_container *child) { | |||
1174 | return list_find(container_get_siblings(child), child); | 1357 | return list_find(container_get_siblings(child), child); |
1175 | } | 1358 | } |
1176 | 1359 | ||
1177 | list_t *container_get_current_siblings(struct sway_container *container) { | ||
1178 | if (container->current.parent) { | ||
1179 | return container->current.parent->current.children; | ||
1180 | } | ||
1181 | return container->current.workspace->current.tiling; | ||
1182 | } | ||
1183 | |||
1184 | void container_handle_fullscreen_reparent(struct sway_container *con) { | 1360 | void container_handle_fullscreen_reparent(struct sway_container *con) { |
1185 | if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace || | 1361 | if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace || |
1186 | con->pending.workspace->fullscreen == con) { | 1362 | con->pending.workspace->fullscreen == con) { |
@@ -1395,7 +1571,7 @@ bool container_find_and_unmark(char *mark) { | |||
1395 | if (strcmp(con_mark, mark) == 0) { | 1571 | if (strcmp(con_mark, mark) == 0) { |
1396 | free(con_mark); | 1572 | free(con_mark); |
1397 | list_del(con->marks, i); | 1573 | list_del(con->marks, i); |
1398 | container_update_marks_textures(con); | 1574 | container_update_marks(con); |
1399 | ipc_event_window(con, "mark"); | 1575 | ipc_event_window(con, "mark"); |
1400 | return true; | 1576 | return true; |
1401 | } | 1577 | } |
@@ -1426,70 +1602,15 @@ void container_add_mark(struct sway_container *con, char *mark) { | |||
1426 | ipc_event_window(con, "mark"); | 1602 | ipc_event_window(con, "mark"); |
1427 | } | 1603 | } |
1428 | 1604 | ||
1429 | static void update_marks_texture(struct sway_container *con, | ||
1430 | struct wlr_texture **texture, struct border_colors *class) { | ||
1431 | struct sway_output *output = container_get_effective_output(con); | ||
1432 | if (!output) { | ||
1433 | return; | ||
1434 | } | ||
1435 | if (*texture) { | ||
1436 | wlr_texture_destroy(*texture); | ||
1437 | *texture = NULL; | ||
1438 | } | ||
1439 | if (!con->marks->length) { | ||
1440 | return; | ||
1441 | } | ||
1442 | |||
1443 | size_t len = 0; | ||
1444 | for (int i = 0; i < con->marks->length; ++i) { | ||
1445 | char *mark = con->marks->items[i]; | ||
1446 | if (mark[0] != '_') { | ||
1447 | len += strlen(mark) + 2; | ||
1448 | } | ||
1449 | } | ||
1450 | char *buffer = calloc(len + 1, 1); | ||
1451 | char *part = malloc(len + 1); | ||
1452 | |||
1453 | if (!sway_assert(buffer && part, "Unable to allocate memory")) { | ||
1454 | free(buffer); | ||
1455 | return; | ||
1456 | } | ||
1457 | |||
1458 | for (int i = 0; i < con->marks->length; ++i) { | ||
1459 | char *mark = con->marks->items[i]; | ||
1460 | if (mark[0] != '_') { | ||
1461 | snprintf(part, len + 1, "[%s]", mark); | ||
1462 | strcat(buffer, part); | ||
1463 | } | ||
1464 | } | ||
1465 | free(part); | ||
1466 | |||
1467 | render_titlebar_text_texture(output, con, texture, class, false, buffer); | ||
1468 | |||
1469 | free(buffer); | ||
1470 | } | ||
1471 | |||
1472 | void container_update_marks_textures(struct sway_container *con) { | ||
1473 | if (!config->show_marks) { | ||
1474 | return; | ||
1475 | } | ||
1476 | update_marks_texture(con, &con->marks_focused, | ||
1477 | &config->border_colors.focused); | ||
1478 | update_marks_texture(con, &con->marks_focused_inactive, | ||
1479 | &config->border_colors.focused_inactive); | ||
1480 | update_marks_texture(con, &con->marks_unfocused, | ||
1481 | &config->border_colors.unfocused); | ||
1482 | update_marks_texture(con, &con->marks_urgent, | ||
1483 | &config->border_colors.urgent); | ||
1484 | update_marks_texture(con, &con->marks_focused_tab_title, | ||
1485 | &config->border_colors.focused_tab_title); | ||
1486 | container_damage_whole(con); | ||
1487 | } | ||
1488 | |||
1489 | void container_raise_floating(struct sway_container *con) { | 1605 | void container_raise_floating(struct sway_container *con) { |
1490 | // Bring container to front by putting it at the end of the floating list. | 1606 | // Bring container to front by putting it at the end of the floating list. |
1491 | struct sway_container *floater = container_toplevel_ancestor(con); | 1607 | struct sway_container *floater = container_toplevel_ancestor(con); |
1492 | if (container_is_floating(floater) && floater->pending.workspace) { | 1608 | if (container_is_floating(floater) && floater->pending.workspace) { |
1609 | // it's okay to just raise the scene directly instead of waiting | ||
1610 | // for the transaction to go through. We won't be reconfiguring | ||
1611 | // surfaces | ||
1612 | wlr_scene_node_raise_to_top(&floater->scene_tree->node); | ||
1613 | |||
1493 | list_move_to_end(floater->pending.workspace->floating, floater); | 1614 | list_move_to_end(floater->pending.workspace->floating, floater); |
1494 | node_set_dirty(&floater->pending.workspace->node); | 1615 | node_set_dirty(&floater->pending.workspace->node); |
1495 | } | 1616 | } |