diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 151 |
1 files changed, 148 insertions, 3 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 322f2f67..458ed7ff 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -39,6 +39,7 @@ struct sway_container *container_create(struct sway_view *view) { | |||
39 | c->children = create_list(); | 39 | c->children = create_list(); |
40 | c->current.children = create_list(); | 40 | c->current.children = create_list(); |
41 | } | 41 | } |
42 | c->marks = create_list(); | ||
42 | c->outputs = create_list(); | 43 | c->outputs = create_list(); |
43 | 44 | ||
44 | wl_signal_init(&c->events.destroy); | 45 | wl_signal_init(&c->events.destroy); |
@@ -66,6 +67,13 @@ void container_destroy(struct sway_container *con) { | |||
66 | list_free(con->current.children); | 67 | list_free(con->current.children); |
67 | list_free(con->outputs); | 68 | list_free(con->outputs); |
68 | 69 | ||
70 | list_foreach(con->marks, free); | ||
71 | list_free(con->marks); | ||
72 | wlr_texture_destroy(con->marks_focused); | ||
73 | wlr_texture_destroy(con->marks_focused_inactive); | ||
74 | wlr_texture_destroy(con->marks_unfocused); | ||
75 | wlr_texture_destroy(con->marks_urgent); | ||
76 | |||
69 | if (con->view) { | 77 | if (con->view) { |
70 | if (con->view->container == con) { | 78 | if (con->view->container == con) { |
71 | con->view->container = NULL; | 79 | con->view->container = NULL; |
@@ -996,9 +1004,7 @@ void container_discover_outputs(struct sway_container *con) { | |||
996 | double new_scale = new_output ? new_output->wlr_output->scale : -1; | 1004 | double new_scale = new_output ? new_output->wlr_output->scale : -1; |
997 | if (old_scale != new_scale) { | 1005 | if (old_scale != new_scale) { |
998 | container_update_title_textures(con); | 1006 | container_update_title_textures(con); |
999 | if (con->view) { | 1007 | container_update_marks_textures(con); |
1000 | view_update_marks_textures(con->view); | ||
1001 | } | ||
1002 | } | 1008 | } |
1003 | } | 1009 | } |
1004 | 1010 | ||
@@ -1218,3 +1224,142 @@ bool container_is_transient_for(struct sway_container *child, | |||
1218 | child->view && ancestor->view && | 1224 | child->view && ancestor->view && |
1219 | view_is_transient_for(child->view, ancestor->view); | 1225 | view_is_transient_for(child->view, ancestor->view); |
1220 | } | 1226 | } |
1227 | |||
1228 | static bool find_by_mark_iterator(struct sway_container *con, void *data) { | ||
1229 | char *mark = data; | ||
1230 | return container_has_mark(con, mark); | ||
1231 | } | ||
1232 | |||
1233 | struct sway_container *container_find_mark(char *mark) { | ||
1234 | return root_find_container(find_by_mark_iterator, mark); | ||
1235 | } | ||
1236 | |||
1237 | bool container_find_and_unmark(char *mark) { | ||
1238 | struct sway_container *con = root_find_container( | ||
1239 | find_by_mark_iterator, mark); | ||
1240 | if (!con) { | ||
1241 | return false; | ||
1242 | } | ||
1243 | |||
1244 | for (int i = 0; i < con->marks->length; ++i) { | ||
1245 | char *con_mark = con->marks->items[i]; | ||
1246 | if (strcmp(con_mark, mark) == 0) { | ||
1247 | free(con_mark); | ||
1248 | list_del(con->marks, i); | ||
1249 | container_update_marks_textures(con); | ||
1250 | ipc_event_window(con, "mark"); | ||
1251 | return true; | ||
1252 | } | ||
1253 | } | ||
1254 | return false; | ||
1255 | } | ||
1256 | |||
1257 | void container_clear_marks(struct sway_container *con) { | ||
1258 | list_foreach(con->marks, free); | ||
1259 | con->marks->length = 0; | ||
1260 | ipc_event_window(con, "mark"); | ||
1261 | } | ||
1262 | |||
1263 | bool container_has_mark(struct sway_container *con, char *mark) { | ||
1264 | for (int i = 0; i < con->marks->length; ++i) { | ||
1265 | char *item = con->marks->items[i]; | ||
1266 | if (strcmp(item, mark) == 0) { | ||
1267 | return true; | ||
1268 | } | ||
1269 | } | ||
1270 | return false; | ||
1271 | } | ||
1272 | |||
1273 | void container_add_mark(struct sway_container *con, char *mark) { | ||
1274 | list_add(con->marks, strdup(mark)); | ||
1275 | ipc_event_window(con, "mark"); | ||
1276 | } | ||
1277 | |||
1278 | static void update_marks_texture(struct sway_container *con, | ||
1279 | struct wlr_texture **texture, struct border_colors *class) { | ||
1280 | struct sway_output *output = container_get_effective_output(con); | ||
1281 | if (!output) { | ||
1282 | return; | ||
1283 | } | ||
1284 | if (*texture) { | ||
1285 | wlr_texture_destroy(*texture); | ||
1286 | *texture = NULL; | ||
1287 | } | ||
1288 | if (!con->marks->length) { | ||
1289 | return; | ||
1290 | } | ||
1291 | |||
1292 | size_t len = 0; | ||
1293 | for (int i = 0; i < con->marks->length; ++i) { | ||
1294 | char *mark = con->marks->items[i]; | ||
1295 | if (mark[0] != '_') { | ||
1296 | len += strlen(mark) + 2; | ||
1297 | } | ||
1298 | } | ||
1299 | char *buffer = calloc(len + 1, 1); | ||
1300 | char *part = malloc(len + 1); | ||
1301 | |||
1302 | if (!sway_assert(buffer && part, "Unable to allocate memory")) { | ||
1303 | free(buffer); | ||
1304 | return; | ||
1305 | } | ||
1306 | |||
1307 | for (int i = 0; i < con->marks->length; ++i) { | ||
1308 | char *mark = con->marks->items[i]; | ||
1309 | if (mark[0] != '_') { | ||
1310 | sprintf(part, "[%s]", mark); | ||
1311 | strcat(buffer, part); | ||
1312 | } | ||
1313 | } | ||
1314 | free(part); | ||
1315 | |||
1316 | double scale = output->wlr_output->scale; | ||
1317 | int width = 0; | ||
1318 | int height = con->title_height * scale; | ||
1319 | |||
1320 | cairo_t *c = cairo_create(NULL); | ||
1321 | get_text_size(c, config->font, &width, NULL, NULL, scale, false, | ||
1322 | "%s", buffer); | ||
1323 | cairo_destroy(c); | ||
1324 | |||
1325 | cairo_surface_t *surface = cairo_image_surface_create( | ||
1326 | CAIRO_FORMAT_ARGB32, width, height); | ||
1327 | cairo_t *cairo = cairo_create(surface); | ||
1328 | cairo_set_source_rgba(cairo, class->background[0], class->background[1], | ||
1329 | class->background[2], class->background[3]); | ||
1330 | cairo_paint(cairo); | ||
1331 | PangoContext *pango = pango_cairo_create_context(cairo); | ||
1332 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
1333 | cairo_set_source_rgba(cairo, class->text[0], class->text[1], | ||
1334 | class->text[2], class->text[3]); | ||
1335 | cairo_move_to(cairo, 0, 0); | ||
1336 | |||
1337 | pango_printf(cairo, config->font, scale, false, "%s", buffer); | ||
1338 | |||
1339 | cairo_surface_flush(surface); | ||
1340 | unsigned char *data = cairo_image_surface_get_data(surface); | ||
1341 | int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); | ||
1342 | struct wlr_renderer *renderer = wlr_backend_get_renderer( | ||
1343 | output->wlr_output->backend); | ||
1344 | *texture = wlr_texture_from_pixels( | ||
1345 | renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); | ||
1346 | cairo_surface_destroy(surface); | ||
1347 | g_object_unref(pango); | ||
1348 | cairo_destroy(cairo); | ||
1349 | free(buffer); | ||
1350 | } | ||
1351 | |||
1352 | void container_update_marks_textures(struct sway_container *con) { | ||
1353 | if (!config->show_marks) { | ||
1354 | return; | ||
1355 | } | ||
1356 | update_marks_texture(con, &con->marks_focused, | ||
1357 | &config->border_colors.focused); | ||
1358 | update_marks_texture(con, &con->marks_focused_inactive, | ||
1359 | &config->border_colors.focused_inactive); | ||
1360 | update_marks_texture(con, &con->marks_unfocused, | ||
1361 | &config->border_colors.unfocused); | ||
1362 | update_marks_texture(con, &con->marks_urgent, | ||
1363 | &config->border_colors.urgent); | ||
1364 | container_damage_whole(con); | ||
1365 | } | ||