mirror of
https://github.com/NickHu/sway
synced 2024-12-26 21:58:30 +01:00
scene_graph: Port container server side decorations
This commit is contained in:
parent
188811f808
commit
6d7b1321db
9 changed files with 378 additions and 253 deletions
|
@ -76,6 +76,9 @@ struct sway_container {
|
||||||
|
|
||||||
struct wlr_scene_tree *border;
|
struct wlr_scene_tree *border;
|
||||||
struct wlr_scene_tree *background;
|
struct wlr_scene_tree *background;
|
||||||
|
|
||||||
|
struct sway_text_node *title_text;
|
||||||
|
struct sway_text_node *marks_text;
|
||||||
} title_bar;
|
} title_bar;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -94,6 +97,7 @@ struct sway_container {
|
||||||
|
|
||||||
char *title; // The view's title (unformatted)
|
char *title; // The view's title (unformatted)
|
||||||
char *formatted_title; // The title displayed in the title bar
|
char *formatted_title; // The title displayed in the title bar
|
||||||
|
int title_width;
|
||||||
|
|
||||||
enum sway_container_layout prev_split_layout;
|
enum sway_container_layout prev_split_layout;
|
||||||
|
|
||||||
|
@ -141,18 +145,7 @@ struct sway_container {
|
||||||
|
|
||||||
float alpha;
|
float alpha;
|
||||||
|
|
||||||
struct wlr_texture *title_focused;
|
|
||||||
struct wlr_texture *title_focused_inactive;
|
|
||||||
struct wlr_texture *title_focused_tab_title;
|
|
||||||
struct wlr_texture *title_unfocused;
|
|
||||||
struct wlr_texture *title_urgent;
|
|
||||||
|
|
||||||
list_t *marks; // char *
|
list_t *marks; // char *
|
||||||
struct wlr_texture *marks_focused;
|
|
||||||
struct wlr_texture *marks_focused_inactive;
|
|
||||||
struct wlr_texture *marks_focused_tab_title;
|
|
||||||
struct wlr_texture *marks_unfocused;
|
|
||||||
struct wlr_texture *marks_urgent;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
|
@ -194,7 +187,9 @@ void container_reap_empty(struct sway_container *con);
|
||||||
|
|
||||||
struct sway_container *container_flatten(struct sway_container *container);
|
struct sway_container *container_flatten(struct sway_container *container);
|
||||||
|
|
||||||
void container_update_title_textures(struct sway_container *container);
|
void container_update_title_bar(struct sway_container *container);
|
||||||
|
|
||||||
|
void container_update_marks(struct sway_container *container);
|
||||||
|
|
||||||
size_t container_build_representation(enum sway_container_layout layout,
|
size_t container_build_representation(enum sway_container_layout layout,
|
||||||
list_t *children, char *buffer);
|
list_t *children, char *buffer);
|
||||||
|
@ -230,11 +225,6 @@ void container_set_geometry_from_content(struct sway_container *con);
|
||||||
*/
|
*/
|
||||||
bool container_is_floating(struct sway_container *container);
|
bool container_is_floating(struct sway_container *container);
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as above, but for current container state.
|
|
||||||
*/
|
|
||||||
bool container_is_current_floating(struct sway_container *container);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a container's box in layout coordinates.
|
* Get a container's box in layout coordinates.
|
||||||
*/
|
*/
|
||||||
|
@ -308,15 +298,10 @@ void container_discover_outputs(struct sway_container *con);
|
||||||
|
|
||||||
enum sway_container_layout container_parent_layout(struct sway_container *con);
|
enum sway_container_layout container_parent_layout(struct sway_container *con);
|
||||||
|
|
||||||
enum sway_container_layout container_current_parent_layout(
|
|
||||||
struct sway_container *con);
|
|
||||||
|
|
||||||
list_t *container_get_siblings(struct sway_container *container);
|
list_t *container_get_siblings(struct sway_container *container);
|
||||||
|
|
||||||
int container_sibling_index(struct sway_container *child);
|
int container_sibling_index(struct sway_container *child);
|
||||||
|
|
||||||
list_t *container_get_current_siblings(struct sway_container *container);
|
|
||||||
|
|
||||||
void container_handle_fullscreen_reparent(struct sway_container *con);
|
void container_handle_fullscreen_reparent(struct sway_container *con);
|
||||||
|
|
||||||
void container_add_child(struct sway_container *parent,
|
void container_add_child(struct sway_container *parent,
|
||||||
|
@ -364,8 +349,6 @@ bool container_has_mark(struct sway_container *container, char *mark);
|
||||||
|
|
||||||
void container_add_mark(struct sway_container *container, char *mark);
|
void container_add_mark(struct sway_container *container, char *mark);
|
||||||
|
|
||||||
void container_update_marks_textures(struct sway_container *container);
|
|
||||||
|
|
||||||
void container_raise_floating(struct sway_container *con);
|
void container_raise_floating(struct sway_container *con);
|
||||||
|
|
||||||
bool container_is_scratchpad_hidden(struct sway_container *con);
|
bool container_is_scratchpad_hidden(struct sway_container *con);
|
||||||
|
@ -389,4 +372,10 @@ bool container_is_sticky_or_child(struct sway_container *con);
|
||||||
*/
|
*/
|
||||||
int container_squash(struct sway_container *con);
|
int container_squash(struct sway_container *con);
|
||||||
|
|
||||||
|
void container_arrange_title_bar(struct sway_container *con);
|
||||||
|
|
||||||
|
void container_update(struct sway_container *con);
|
||||||
|
|
||||||
|
void container_update_itself_and_parents(struct sway_container *con);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
#include "sway/tree/container.h"
|
#include "sway/tree/container.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void rebuild_textures_iterator(struct sway_container *con, void *data) {
|
static void container_update_iterator(struct sway_container *con, void *data) {
|
||||||
container_update_marks_textures(con);
|
container_update(con);
|
||||||
container_update_title_textures(con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
|
static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
|
||||||
|
@ -51,7 +50,7 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
|
||||||
memcpy(class, &colors, sizeof(struct border_colors));
|
memcpy(class, &colors, sizeof(struct border_colors));
|
||||||
|
|
||||||
if (config->active) {
|
if (config->active) {
|
||||||
root_for_each_container(rebuild_textures_iterator, NULL);
|
root_for_each_container(container_update_iterator, NULL);
|
||||||
|
|
||||||
for (int i = 0; i < root->outputs->length; ++i) {
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
|
|
|
@ -59,7 +59,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free(mark);
|
free(mark);
|
||||||
container_update_marks_textures(container);
|
container_update_marks(container);
|
||||||
if (container->view) {
|
if (container->view) {
|
||||||
view_execute_criteria(container->view);
|
view_execute_criteria(container->view);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
static void rebuild_textures_iterator(struct sway_container *con, void *data) {
|
static void title_bar_update_iterator(struct sway_container *con, void *data) {
|
||||||
container_update_marks_textures(con);
|
container_update_title_bar(con);
|
||||||
container_update_title_textures(con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_reload(void *data) {
|
static void do_reload(void *data) {
|
||||||
|
@ -48,7 +47,7 @@ static void do_reload(void *data) {
|
||||||
}
|
}
|
||||||
list_free_items_and_destroy(bar_ids);
|
list_free_items_and_destroy(bar_ids);
|
||||||
|
|
||||||
root_for_each_container(rebuild_textures_iterator, NULL);
|
root_for_each_container(title_bar_update_iterator, NULL);
|
||||||
|
|
||||||
arrange_root();
|
arrange_root();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void rebuild_marks_iterator(struct sway_container *con, void *data) {
|
static void title_bar_update_iterator(struct sway_container *con, void *data) {
|
||||||
container_update_marks_textures(con);
|
container_update_marks(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd_results *cmd_show_marks(int argc, char **argv) {
|
struct cmd_results *cmd_show_marks(int argc, char **argv) {
|
||||||
|
@ -23,7 +23,7 @@ struct cmd_results *cmd_show_marks(int argc, char **argv) {
|
||||||
config->show_marks = parse_boolean(argv[0], config->show_marks);
|
config->show_marks = parse_boolean(argv[0], config->show_marks);
|
||||||
|
|
||||||
if (config->show_marks) {
|
if (config->show_marks) {
|
||||||
root_for_each_container(rebuild_marks_iterator, NULL);
|
root_for_each_container(title_bar_update_iterator, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < root->outputs->length; ++i) {
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
#include "sway/tree/container.h"
|
#include "sway/tree/container.h"
|
||||||
#include "sway/tree/root.h"
|
#include "sway/tree/root.h"
|
||||||
|
|
||||||
|
static void arrange_title_bar_iterator(struct sway_container *con, void *data) {
|
||||||
|
container_arrange_title_bar(con);
|
||||||
|
}
|
||||||
|
|
||||||
struct cmd_results *cmd_title_align(int argc, char **argv) {
|
struct cmd_results *cmd_title_align(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) {
|
if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
@ -21,6 +25,8 @@ struct cmd_results *cmd_title_align(int argc, char **argv) {
|
||||||
"Expected 'title_align left|center|right'");
|
"Expected 'title_align left|center|right'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root_for_each_container(arrange_title_bar_iterator, NULL);
|
||||||
|
|
||||||
for (int i = 0; i < root->outputs->length; ++i) {
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
output_damage_whole(output);
|
output_damage_whole(output);
|
||||||
|
|
|
@ -8,9 +8,13 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
|
|
||||||
static void remove_all_marks_iterator(struct sway_container *con, void *data) {
|
static void remove_mark(struct sway_container *con) {
|
||||||
container_clear_marks(con);
|
container_clear_marks(con);
|
||||||
container_update_marks_textures(con);
|
container_update_marks(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_all_marks_iterator(struct sway_container *con, void *data) {
|
||||||
|
remove_mark(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unmark Remove all marks from all views
|
// unmark Remove all marks from all views
|
||||||
|
@ -38,8 +42,7 @@ struct cmd_results *cmd_unmark(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
} else if (con && !mark) {
|
} else if (con && !mark) {
|
||||||
// Clear all marks from the given container
|
// Clear all marks from the given container
|
||||||
container_clear_marks(con);
|
remove_mark(con);
|
||||||
container_update_marks_textures(con);
|
|
||||||
} else if (!con && mark) {
|
} else if (!con && mark) {
|
||||||
// Remove mark from whichever container has it
|
// Remove mark from whichever container has it
|
||||||
container_find_and_unmark(mark);
|
container_find_and_unmark(mark);
|
||||||
|
|
|
@ -8,15 +8,13 @@
|
||||||
#include <wlr/types/wlr_output_layout.h>
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||||
#include "cairo_util.h"
|
|
||||||
#include "pango.h"
|
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/desktop.h"
|
|
||||||
#include "sway/desktop/transaction.h"
|
#include "sway/desktop/transaction.h"
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
#include "sway/ipc-server.h"
|
#include "sway/ipc-server.h"
|
||||||
#include "sway/scene_descriptor.h"
|
#include "sway/scene_descriptor.h"
|
||||||
|
#include "sway/sway_text_node.h"
|
||||||
#include "sway/output.h"
|
#include "sway/output.h"
|
||||||
#include "sway/server.h"
|
#include "sway/server.h"
|
||||||
#include "sway/surface.h"
|
#include "sway/surface.h"
|
||||||
|
@ -120,9 +118,328 @@ struct sway_container *container_create(struct sway_view *view) {
|
||||||
wl_signal_init(&c->events.destroy);
|
wl_signal_init(&c->events.destroy);
|
||||||
wl_signal_emit_mutable(&root->events.new_node, &c->node);
|
wl_signal_emit_mutable(&root->events.new_node, &c->node);
|
||||||
|
|
||||||
|
container_update(c);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool container_is_focused(struct sway_container *con, void *data) {
|
||||||
|
return con->current.focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool container_has_focused_child(struct sway_container *con) {
|
||||||
|
return container_find_child(con, container_is_focused, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool container_is_current_parent_focused(struct sway_container *con) {
|
||||||
|
if (con->current.parent) {
|
||||||
|
struct sway_container *parent = con->current.parent;
|
||||||
|
return parent->current.focused || container_is_current_parent_focused(parent);
|
||||||
|
} else if (con->current.workspace) {
|
||||||
|
struct sway_workspace *ws = con->current.workspace;
|
||||||
|
return ws->current.focused;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct border_colors *container_get_current_colors(
|
||||||
|
struct sway_container *con) {
|
||||||
|
struct border_colors *colors;
|
||||||
|
|
||||||
|
bool urgent = con->view ?
|
||||||
|
view_is_urgent(con->view) : container_has_urgent_child(con);
|
||||||
|
struct sway_container *active_child;
|
||||||
|
|
||||||
|
if (con->current.parent) {
|
||||||
|
active_child = con->current.parent->current.focused_inactive_child;
|
||||||
|
} else if (con->current.workspace) {
|
||||||
|
active_child = con->current.workspace->current.focused_inactive_child;
|
||||||
|
} else {
|
||||||
|
active_child = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urgent) {
|
||||||
|
colors = &config->border_colors.urgent;
|
||||||
|
} else if (con->current.focused || container_is_current_parent_focused(con)) {
|
||||||
|
colors = &config->border_colors.focused;
|
||||||
|
} else if (config->has_focused_tab_title && container_has_focused_child(con)) {
|
||||||
|
colors = &config->border_colors.focused_tab_title;
|
||||||
|
} else if (con == active_child) {
|
||||||
|
colors = &config->border_colors.focused_inactive;
|
||||||
|
} else {
|
||||||
|
colors = &config->border_colors.unfocused;
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool container_is_current_floating(struct sway_container *container) {
|
||||||
|
if (!container->current.parent && container->current.workspace &&
|
||||||
|
list_find(container->current.workspace->floating, container) != -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (container->scratchpad) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scene rect wants premultiplied colors
|
||||||
|
static void scene_rect_set_color(struct wlr_scene_rect *rect,
|
||||||
|
const float color[4], float opacity) {
|
||||||
|
const float premultiplied[] = {
|
||||||
|
color[0] * color[3] * opacity,
|
||||||
|
color[1] * color[3] * opacity,
|
||||||
|
color[2] * color[3] * opacity,
|
||||||
|
color[3] * opacity,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_scene_rect_set_color(rect, premultiplied);
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_update(struct sway_container *con) {
|
||||||
|
struct border_colors *colors = container_get_current_colors(con);
|
||||||
|
list_t *siblings = NULL;
|
||||||
|
enum sway_container_layout layout = L_NONE;
|
||||||
|
float alpha = con->alpha;
|
||||||
|
|
||||||
|
if (con->current.parent) {
|
||||||
|
siblings = con->current.parent->current.children;
|
||||||
|
layout = con->current.parent->current.layout;
|
||||||
|
} else if (con->current.workspace) {
|
||||||
|
siblings = con->current.workspace->current.tiling;
|
||||||
|
layout = con->current.workspace->current.layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
float bottom[4], right[4];
|
||||||
|
memcpy(bottom, colors->child_border, sizeof(bottom));
|
||||||
|
memcpy(right, colors->child_border, sizeof(right));
|
||||||
|
|
||||||
|
if (!container_is_current_floating(con) && siblings && siblings->length == 1) {
|
||||||
|
if (layout == L_HORIZ) {
|
||||||
|
memcpy(right, colors->indicator, sizeof(right));
|
||||||
|
} else if (layout == L_VERT) {
|
||||||
|
memcpy(bottom, colors->indicator, sizeof(bottom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_scene_node *node;
|
||||||
|
wl_list_for_each(node, &con->title_bar.border->children, link) {
|
||||||
|
struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node);
|
||||||
|
scene_rect_set_color(rect, colors->border, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_for_each(node, &con->title_bar.background->children, link) {
|
||||||
|
struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node);
|
||||||
|
scene_rect_set_color(rect, colors->background, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->view) {
|
||||||
|
scene_rect_set_color(con->border.top, colors->child_border, alpha);
|
||||||
|
scene_rect_set_color(con->border.bottom, bottom, alpha);
|
||||||
|
scene_rect_set_color(con->border.left, colors->child_border, alpha);
|
||||||
|
scene_rect_set_color(con->border.right, right, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->title_bar.title_text) {
|
||||||
|
sway_text_node_set_color(con->title_bar.title_text, colors->text);
|
||||||
|
sway_text_node_set_background(con->title_bar.title_text, colors->background);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->title_bar.marks_text) {
|
||||||
|
sway_text_node_set_color(con->title_bar.marks_text, colors->text);
|
||||||
|
sway_text_node_set_background(con->title_bar.marks_text, colors->background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_update_itself_and_parents(struct sway_container *con) {
|
||||||
|
container_update(con);
|
||||||
|
|
||||||
|
if (con->current.parent) {
|
||||||
|
container_update_itself_and_parents(con->current.parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_rect_list(struct wlr_scene_tree *tree, pixman_region32_t *region) {
|
||||||
|
int len;
|
||||||
|
const pixman_box32_t *rects = pixman_region32_rectangles(region, &len);
|
||||||
|
|
||||||
|
wlr_scene_node_set_enabled(&tree->node, len > 0);
|
||||||
|
if (len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
struct wlr_scene_node *node;
|
||||||
|
wl_list_for_each(node, &tree->children, link) {
|
||||||
|
struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node);
|
||||||
|
wlr_scene_node_set_enabled(&rect->node, i < len);
|
||||||
|
|
||||||
|
if (i < len) {
|
||||||
|
const pixman_box32_t *box = &rects[i++];
|
||||||
|
wlr_scene_node_set_position(&rect->node, box->x1, box->y1);
|
||||||
|
wlr_scene_rect_set_size(rect, box->x2 - box->x1, box->y2 - box->y1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_arrange_title_bar(struct sway_container *con) {
|
||||||
|
enum alignment title_align = config->title_align;
|
||||||
|
int marks_buffer_width = 0;
|
||||||
|
int width = con->title_width;
|
||||||
|
int height = container_titlebar_height();
|
||||||
|
|
||||||
|
pixman_region32_t text_area;
|
||||||
|
pixman_region32_init(&text_area);
|
||||||
|
|
||||||
|
if (con->title_bar.marks_text) {
|
||||||
|
struct sway_text_node *node = con->title_bar.marks_text;
|
||||||
|
marks_buffer_width = node->width;
|
||||||
|
|
||||||
|
int h_padding;
|
||||||
|
if (title_align == ALIGN_RIGHT) {
|
||||||
|
h_padding = config->titlebar_h_padding;
|
||||||
|
} else {
|
||||||
|
h_padding = width - config->titlebar_h_padding - marks_buffer_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
h_padding = MAX(h_padding, 0);
|
||||||
|
|
||||||
|
int alloc_width = MIN((int)node->width,
|
||||||
|
width - h_padding - config->titlebar_h_padding);
|
||||||
|
sway_text_node_set_max_width(node, alloc_width);
|
||||||
|
wlr_scene_node_set_position(node->node,
|
||||||
|
h_padding, (height - node->height) >> 1);
|
||||||
|
|
||||||
|
pixman_region32_union_rect(&text_area, &text_area,
|
||||||
|
node->node->x, node->node->y, alloc_width, node->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->title_bar.title_text) {
|
||||||
|
struct sway_text_node *node = con->title_bar.title_text;
|
||||||
|
|
||||||
|
int h_padding;
|
||||||
|
if (title_align == ALIGN_RIGHT) {
|
||||||
|
h_padding = width - config->titlebar_h_padding - node->width;
|
||||||
|
} else if (title_align == ALIGN_CENTER) {
|
||||||
|
h_padding = ((int)width - marks_buffer_width - node->width) >> 1;
|
||||||
|
} else {
|
||||||
|
h_padding = config->titlebar_h_padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
h_padding = MAX(h_padding, 0);
|
||||||
|
|
||||||
|
int alloc_width = MIN((int) node->width,
|
||||||
|
width - h_padding - config->titlebar_h_padding);
|
||||||
|
sway_text_node_set_max_width(node, alloc_width);
|
||||||
|
wlr_scene_node_set_position(node->node,
|
||||||
|
h_padding, (height - node->height) >> 1);
|
||||||
|
|
||||||
|
pixman_region32_union_rect(&text_area, &text_area,
|
||||||
|
node->node->x, node->node->y, alloc_width, node->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// silence pixman errors
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
pixman_region32_fini(&text_area);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_t background, border;
|
||||||
|
|
||||||
|
int thickness = config->titlebar_border_thickness;
|
||||||
|
pixman_region32_init_rect(&background,
|
||||||
|
thickness, thickness,
|
||||||
|
width - thickness * 2, height - thickness * 2);
|
||||||
|
pixman_region32_init_rect(&border, 0, 0, width, height);
|
||||||
|
pixman_region32_subtract(&border, &border, &background);
|
||||||
|
|
||||||
|
pixman_region32_subtract(&background, &background, &text_area);
|
||||||
|
pixman_region32_fini(&text_area);
|
||||||
|
|
||||||
|
update_rect_list(con->title_bar.background, &background);
|
||||||
|
pixman_region32_fini(&background);
|
||||||
|
|
||||||
|
update_rect_list(con->title_bar.border, &border);
|
||||||
|
pixman_region32_fini(&border);
|
||||||
|
|
||||||
|
container_update(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_update_marks(struct sway_container *con) {
|
||||||
|
char *buffer = NULL;
|
||||||
|
|
||||||
|
if (config->show_marks && con->marks->length) {
|
||||||
|
size_t len = 0;
|
||||||
|
for (int i = 0; i < con->marks->length; ++i) {
|
||||||
|
char *mark = con->marks->items[i];
|
||||||
|
if (mark[0] != '_') {
|
||||||
|
len += strlen(mark) + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer = calloc(len + 1, 1);
|
||||||
|
char *part = malloc(len + 1);
|
||||||
|
|
||||||
|
if (!sway_assert(buffer && part, "Unable to allocate memory")) {
|
||||||
|
free(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < con->marks->length; ++i) {
|
||||||
|
char *mark = con->marks->items[i];
|
||||||
|
if (mark[0] != '_') {
|
||||||
|
snprintf(part, len + 1, "[%s]", mark);
|
||||||
|
strcat(buffer, part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
if (con->title_bar.marks_text) {
|
||||||
|
wlr_scene_node_destroy(con->title_bar.marks_text->node);
|
||||||
|
con->title_bar.marks_text = NULL;
|
||||||
|
}
|
||||||
|
} else if (!con->title_bar.marks_text) {
|
||||||
|
struct border_colors *colors = container_get_current_colors(con);
|
||||||
|
|
||||||
|
con->title_bar.marks_text = sway_text_node_create(con->title_bar.tree,
|
||||||
|
buffer, colors->text, false);
|
||||||
|
} else {
|
||||||
|
sway_text_node_set_text(con->title_bar.marks_text, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
container_arrange_title_bar(con);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void container_update_title_bar(struct sway_container *con) {
|
||||||
|
if (!con->formatted_title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct border_colors *colors = container_get_current_colors(con);
|
||||||
|
|
||||||
|
if (con->title_bar.title_text) {
|
||||||
|
wlr_scene_node_destroy(con->title_bar.title_text->node);
|
||||||
|
con->title_bar.title_text = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->title_bar.title_text = sway_text_node_create(con->title_bar.tree,
|
||||||
|
con->formatted_title, colors->text, config->pango_markup);
|
||||||
|
|
||||||
|
// we always have to remake these text buffers completely for text font
|
||||||
|
// changes etc...
|
||||||
|
if (con->title_bar.marks_text) {
|
||||||
|
wlr_scene_node_destroy(con->title_bar.marks_text->node);
|
||||||
|
con->title_bar.marks_text = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
container_update_marks(con);
|
||||||
|
container_arrange_title_bar(con);
|
||||||
|
}
|
||||||
|
|
||||||
void container_destroy(struct sway_container *con) {
|
void container_destroy(struct sway_container *con) {
|
||||||
if (!sway_assert(con->node.destroying,
|
if (!sway_assert(con->node.destroying,
|
||||||
"Tried to free container which wasn't marked as destroying")) {
|
"Tried to free container which wasn't marked as destroying")) {
|
||||||
|
@ -134,21 +451,11 @@ void container_destroy(struct sway_container *con) {
|
||||||
}
|
}
|
||||||
free(con->title);
|
free(con->title);
|
||||||
free(con->formatted_title);
|
free(con->formatted_title);
|
||||||
wlr_texture_destroy(con->title_focused);
|
|
||||||
wlr_texture_destroy(con->title_focused_inactive);
|
|
||||||
wlr_texture_destroy(con->title_unfocused);
|
|
||||||
wlr_texture_destroy(con->title_urgent);
|
|
||||||
wlr_texture_destroy(con->title_focused_tab_title);
|
|
||||||
list_free(con->pending.children);
|
list_free(con->pending.children);
|
||||||
list_free(con->current.children);
|
list_free(con->current.children);
|
||||||
list_free(con->outputs);
|
list_free(con->outputs);
|
||||||
|
|
||||||
list_free_items_and_destroy(con->marks);
|
list_free_items_and_destroy(con->marks);
|
||||||
wlr_texture_destroy(con->marks_focused);
|
|
||||||
wlr_texture_destroy(con->marks_focused_inactive);
|
|
||||||
wlr_texture_destroy(con->marks_unfocused);
|
|
||||||
wlr_texture_destroy(con->marks_urgent);
|
|
||||||
wlr_texture_destroy(con->marks_focused_tab_title);
|
|
||||||
|
|
||||||
if (con->view && con->view->container == con) {
|
if (con->view && con->view->container == con) {
|
||||||
con->view->container = NULL;
|
con->view->container = NULL;
|
||||||
|
@ -308,108 +615,6 @@ struct sway_output *container_get_effective_output(struct sway_container *con) {
|
||||||
return con->outputs->items[con->outputs->length - 1];
|
return con->outputs->items[con->outputs->length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_titlebar_text_texture(struct sway_output *output,
|
|
||||||
struct sway_container *con, struct wlr_texture **texture,
|
|
||||||
struct border_colors *class, bool pango_markup, char *text) {
|
|
||||||
double scale = output->wlr_output->scale;
|
|
||||||
int width = 0;
|
|
||||||
int height = config->font_height * scale;
|
|
||||||
int baseline;
|
|
||||||
|
|
||||||
// We must use a non-nil cairo_t for cairo_set_font_options to work.
|
|
||||||
// Therefore, we cannot use cairo_create(NULL).
|
|
||||||
cairo_surface_t *dummy_surface = cairo_image_surface_create(
|
|
||||||
CAIRO_FORMAT_ARGB32, 0, 0);
|
|
||||||
cairo_t *c = cairo_create(dummy_surface);
|
|
||||||
cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST);
|
|
||||||
cairo_font_options_t *fo = cairo_font_options_create();
|
|
||||||
if (output->wlr_output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) {
|
|
||||||
cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY);
|
|
||||||
} else {
|
|
||||||
cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
|
|
||||||
cairo_font_options_set_subpixel_order(fo,
|
|
||||||
to_cairo_subpixel_order(output->wlr_output->subpixel));
|
|
||||||
}
|
|
||||||
cairo_set_font_options(c, fo);
|
|
||||||
get_text_size(c, config->font_description, &width, NULL, &baseline, scale,
|
|
||||||
config->pango_markup, "%s", text);
|
|
||||||
cairo_surface_destroy(dummy_surface);
|
|
||||||
cairo_destroy(c);
|
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height > config->font_height * scale) {
|
|
||||||
height = config->font_height * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_surface_t *surface = cairo_image_surface_create(
|
|
||||||
CAIRO_FORMAT_ARGB32, width, height);
|
|
||||||
cairo_status_t status = cairo_surface_status(surface);
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
|
||||||
sway_log(SWAY_ERROR, "cairo_image_surface_create failed: %s",
|
|
||||||
cairo_status_to_string(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_t *cairo = cairo_create(surface);
|
|
||||||
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
|
|
||||||
cairo_set_font_options(cairo, fo);
|
|
||||||
cairo_font_options_destroy(fo);
|
|
||||||
cairo_set_source_rgba(cairo, class->background[0], class->background[1],
|
|
||||||
class->background[2], class->background[3]);
|
|
||||||
cairo_paint(cairo);
|
|
||||||
PangoContext *pango = pango_cairo_create_context(cairo);
|
|
||||||
cairo_set_source_rgba(cairo, class->text[0], class->text[1],
|
|
||||||
class->text[2], class->text[3]);
|
|
||||||
cairo_move_to(cairo, 0, config->font_baseline * scale - baseline);
|
|
||||||
|
|
||||||
render_text(cairo, config->font_description, scale, pango_markup, "%s", text);
|
|
||||||
|
|
||||||
cairo_surface_flush(surface);
|
|
||||||
unsigned char *data = cairo_image_surface_get_data(surface);
|
|
||||||
int stride = cairo_image_surface_get_stride(surface);
|
|
||||||
struct wlr_renderer *renderer = output->wlr_output->renderer;
|
|
||||||
*texture = wlr_texture_from_pixels(
|
|
||||||
renderer, DRM_FORMAT_ARGB8888, stride, width, height, data);
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
g_object_unref(pango);
|
|
||||||
cairo_destroy(cairo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_title_texture(struct sway_container *con,
|
|
||||||
struct wlr_texture **texture, struct border_colors *class) {
|
|
||||||
struct sway_output *output = container_get_effective_output(con);
|
|
||||||
if (!output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*texture) {
|
|
||||||
wlr_texture_destroy(*texture);
|
|
||||||
*texture = NULL;
|
|
||||||
}
|
|
||||||
if (!con->formatted_title) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
render_titlebar_text_texture(output, con, texture, class,
|
|
||||||
config->pango_markup, con->formatted_title);
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_update_title_textures(struct sway_container *container) {
|
|
||||||
update_title_texture(container, &container->title_focused,
|
|
||||||
&config->border_colors.focused);
|
|
||||||
update_title_texture(container, &container->title_focused_inactive,
|
|
||||||
&config->border_colors.focused_inactive);
|
|
||||||
update_title_texture(container, &container->title_unfocused,
|
|
||||||
&config->border_colors.unfocused);
|
|
||||||
update_title_texture(container, &container->title_urgent,
|
|
||||||
&config->border_colors.urgent);
|
|
||||||
update_title_texture(container, &container->title_focused_tab_title,
|
|
||||||
&config->border_colors.focused_tab_title);
|
|
||||||
container_damage_whole(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate and return the length of the tree representation.
|
* Calculate and return the length of the tree representation.
|
||||||
* An example tree representation is: V[Terminal, Firefox]
|
* An example tree representation is: V[Terminal, Firefox]
|
||||||
|
@ -475,7 +680,13 @@ void container_update_representation(struct sway_container *con) {
|
||||||
}
|
}
|
||||||
container_build_representation(con->pending.layout, con->pending.children,
|
container_build_representation(con->pending.layout, con->pending.children,
|
||||||
con->formatted_title);
|
con->formatted_title);
|
||||||
container_update_title_textures(con);
|
|
||||||
|
if (con->title_bar.title_text) {
|
||||||
|
sway_text_node_set_text(con->title_bar.title_text, con->formatted_title);
|
||||||
|
container_arrange_title_bar(con);
|
||||||
|
} else {
|
||||||
|
container_update_title_bar(con);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (con->pending.parent) {
|
if (con->pending.parent) {
|
||||||
container_update_representation(con->pending.parent);
|
container_update_representation(con->pending.parent);
|
||||||
|
@ -761,17 +972,6 @@ bool container_is_floating(struct sway_container *container) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool container_is_current_floating(struct sway_container *container) {
|
|
||||||
if (!container->current.parent && container->current.workspace &&
|
|
||||||
list_find(container->current.workspace->floating, container) != -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (container->scratchpad) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_get_box(struct sway_container *container, struct wlr_box *box) {
|
void container_get_box(struct sway_container *container, struct wlr_box *box) {
|
||||||
box->x = container->pending.x;
|
box->x = container->pending.x;
|
||||||
box->y = container->pending.y;
|
box->y = container->pending.y;
|
||||||
|
@ -1092,7 +1292,6 @@ void container_discover_outputs(struct sway_container *con) {
|
||||||
.width = con->current.width,
|
.width = con->current.width,
|
||||||
.height = con->current.height,
|
.height = con->current.height,
|
||||||
};
|
};
|
||||||
struct sway_output *old_output = container_get_effective_output(con);
|
|
||||||
|
|
||||||
for (int i = 0; i < root->outputs->length; ++i) {
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
|
@ -1129,14 +1328,6 @@ void container_discover_outputs(struct sway_container *con) {
|
||||||
list_del(con->outputs, index);
|
list_del(con->outputs, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct sway_output *new_output = container_get_effective_output(con);
|
|
||||||
double old_scale = old_output && old_output->enabled ?
|
|
||||||
old_output->wlr_output->scale : -1;
|
|
||||||
double new_scale = new_output ? new_output->wlr_output->scale : -1;
|
|
||||||
if (old_scale != new_scale) {
|
|
||||||
container_update_title_textures(con);
|
|
||||||
container_update_marks_textures(con);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sway_container_layout container_parent_layout(struct sway_container *con) {
|
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) {
|
||||||
return L_NONE;
|
return L_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sway_container_layout container_current_parent_layout(
|
|
||||||
struct sway_container *con) {
|
|
||||||
if (con->current.parent) {
|
|
||||||
return con->current.parent->current.layout;
|
|
||||||
}
|
|
||||||
return con->current.workspace->current.layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_t *container_get_siblings(struct sway_container *container) {
|
list_t *container_get_siblings(struct sway_container *container) {
|
||||||
if (container->pending.parent) {
|
if (container->pending.parent) {
|
||||||
return container->pending.parent->pending.children;
|
return container->pending.parent->pending.children;
|
||||||
|
@ -1174,13 +1357,6 @@ int container_sibling_index(struct sway_container *child) {
|
||||||
return list_find(container_get_siblings(child), child);
|
return list_find(container_get_siblings(child), child);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_t *container_get_current_siblings(struct sway_container *container) {
|
|
||||||
if (container->current.parent) {
|
|
||||||
return container->current.parent->current.children;
|
|
||||||
}
|
|
||||||
return container->current.workspace->current.tiling;
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_handle_fullscreen_reparent(struct sway_container *con) {
|
void container_handle_fullscreen_reparent(struct sway_container *con) {
|
||||||
if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace ||
|
if (con->pending.fullscreen_mode != FULLSCREEN_WORKSPACE || !con->pending.workspace ||
|
||||||
con->pending.workspace->fullscreen == con) {
|
con->pending.workspace->fullscreen == con) {
|
||||||
|
@ -1395,7 +1571,7 @@ bool container_find_and_unmark(char *mark) {
|
||||||
if (strcmp(con_mark, mark) == 0) {
|
if (strcmp(con_mark, mark) == 0) {
|
||||||
free(con_mark);
|
free(con_mark);
|
||||||
list_del(con->marks, i);
|
list_del(con->marks, i);
|
||||||
container_update_marks_textures(con);
|
container_update_marks(con);
|
||||||
ipc_event_window(con, "mark");
|
ipc_event_window(con, "mark");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1426,70 +1602,15 @@ void container_add_mark(struct sway_container *con, char *mark) {
|
||||||
ipc_event_window(con, "mark");
|
ipc_event_window(con, "mark");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_marks_texture(struct sway_container *con,
|
|
||||||
struct wlr_texture **texture, struct border_colors *class) {
|
|
||||||
struct sway_output *output = container_get_effective_output(con);
|
|
||||||
if (!output) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*texture) {
|
|
||||||
wlr_texture_destroy(*texture);
|
|
||||||
*texture = NULL;
|
|
||||||
}
|
|
||||||
if (!con->marks->length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = 0;
|
|
||||||
for (int i = 0; i < con->marks->length; ++i) {
|
|
||||||
char *mark = con->marks->items[i];
|
|
||||||
if (mark[0] != '_') {
|
|
||||||
len += strlen(mark) + 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char *buffer = calloc(len + 1, 1);
|
|
||||||
char *part = malloc(len + 1);
|
|
||||||
|
|
||||||
if (!sway_assert(buffer && part, "Unable to allocate memory")) {
|
|
||||||
free(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < con->marks->length; ++i) {
|
|
||||||
char *mark = con->marks->items[i];
|
|
||||||
if (mark[0] != '_') {
|
|
||||||
snprintf(part, len + 1, "[%s]", mark);
|
|
||||||
strcat(buffer, part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(part);
|
|
||||||
|
|
||||||
render_titlebar_text_texture(output, con, texture, class, false, buffer);
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_update_marks_textures(struct sway_container *con) {
|
|
||||||
if (!config->show_marks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
update_marks_texture(con, &con->marks_focused,
|
|
||||||
&config->border_colors.focused);
|
|
||||||
update_marks_texture(con, &con->marks_focused_inactive,
|
|
||||||
&config->border_colors.focused_inactive);
|
|
||||||
update_marks_texture(con, &con->marks_unfocused,
|
|
||||||
&config->border_colors.unfocused);
|
|
||||||
update_marks_texture(con, &con->marks_urgent,
|
|
||||||
&config->border_colors.urgent);
|
|
||||||
update_marks_texture(con, &con->marks_focused_tab_title,
|
|
||||||
&config->border_colors.focused_tab_title);
|
|
||||||
container_damage_whole(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
void container_raise_floating(struct sway_container *con) {
|
void container_raise_floating(struct sway_container *con) {
|
||||||
// Bring container to front by putting it at the end of the floating list.
|
// Bring container to front by putting it at the end of the floating list.
|
||||||
struct sway_container *floater = container_toplevel_ancestor(con);
|
struct sway_container *floater = container_toplevel_ancestor(con);
|
||||||
if (container_is_floating(floater) && floater->pending.workspace) {
|
if (container_is_floating(floater) && floater->pending.workspace) {
|
||||||
|
// it's okay to just raise the scene directly instead of waiting
|
||||||
|
// for the transaction to go through. We won't be reconfiguring
|
||||||
|
// surfaces
|
||||||
|
wlr_scene_node_raise_to_top(&floater->scene_tree->node);
|
||||||
|
|
||||||
list_move_to_end(floater->pending.workspace->floating, floater);
|
list_move_to_end(floater->pending.workspace->floating, floater);
|
||||||
node_set_dirty(&floater->pending.workspace->node);
|
node_set_dirty(&floater->pending.workspace->node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "sway/scene_descriptor.h"
|
#include "sway/scene_descriptor.h"
|
||||||
#include "sway/server.h"
|
#include "sway/server.h"
|
||||||
#include "sway/surface.h"
|
#include "sway/surface.h"
|
||||||
|
#include "sway/sway_text_node.h"
|
||||||
#include "sway/tree/arrange.h"
|
#include "sway/tree/arrange.h"
|
||||||
#include "sway/tree/container.h"
|
#include "sway/tree/container.h"
|
||||||
#include "sway/tree/view.h"
|
#include "sway/tree/view.h"
|
||||||
|
@ -1337,7 +1338,13 @@ void view_update_title(struct sway_view *view, bool force) {
|
||||||
view->container->title = title ? strdup(title) : NULL;
|
view->container->title = title ? strdup(title) : NULL;
|
||||||
|
|
||||||
// Update title after the global font height is updated
|
// Update title after the global font height is updated
|
||||||
container_update_title_textures(view->container);
|
if (view->container->title_bar.title_text && len) {
|
||||||
|
sway_text_node_set_text(view->container->title_bar.title_text,
|
||||||
|
view->container->formatted_title);
|
||||||
|
container_arrange_title_bar(view->container);
|
||||||
|
} else {
|
||||||
|
container_update_title_bar(view->container);
|
||||||
|
}
|
||||||
|
|
||||||
ipc_event_window(view->container, "title");
|
ipc_event_window(view->container, "title");
|
||||||
|
|
||||||
|
@ -1404,6 +1411,7 @@ void view_set_urgent(struct sway_view *view, bool enable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clock_gettime(CLOCK_MONOTONIC, &view->urgent);
|
clock_gettime(CLOCK_MONOTONIC, &view->urgent);
|
||||||
|
container_update_itself_and_parents(view->container);
|
||||||
} else {
|
} else {
|
||||||
view->urgent = (struct timespec){ 0 };
|
view->urgent = (struct timespec){ 0 };
|
||||||
if (view->urgent_timer) {
|
if (view->urgent_timer) {
|
||||||
|
|
Loading…
Reference in a new issue