2024-09-06 17:00:40 +09:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
|
#include <sfdo-desktop.h>
|
|
|
|
|
#include <sfdo-icon.h>
|
|
|
|
|
#include <sfdo-basedir.h>
|
|
|
|
|
#include <wlr/util/log.h>
|
|
|
|
|
#include "common/mem.h"
|
2024-09-28 11:20:28 +01:00
|
|
|
#include "common/string-helpers.h"
|
2024-09-06 17:00:40 +09:00
|
|
|
#include "config.h"
|
|
|
|
|
#include "icon-loader.h"
|
|
|
|
|
#include "img/img-png.h"
|
|
|
|
|
|
|
|
|
|
#if HAVE_RSVG
|
|
|
|
|
#include "img/img-svg.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "labwc.h"
|
|
|
|
|
|
|
|
|
|
struct icon_loader {
|
|
|
|
|
struct sfdo_desktop_ctx *desktop_ctx;
|
|
|
|
|
struct sfdo_icon_ctx *icon_ctx;
|
|
|
|
|
struct sfdo_desktop_db *desktop_db;
|
|
|
|
|
struct sfdo_icon_theme *icon_theme;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
icon_loader_init(struct server *server)
|
|
|
|
|
{
|
|
|
|
|
struct icon_loader *loader = znew(*loader);
|
|
|
|
|
|
|
|
|
|
struct sfdo_basedir_ctx *basedir_ctx = sfdo_basedir_ctx_create();
|
|
|
|
|
if (!basedir_ctx) {
|
|
|
|
|
goto err_basedir_ctx;
|
|
|
|
|
}
|
|
|
|
|
loader->desktop_ctx = sfdo_desktop_ctx_create(basedir_ctx);
|
|
|
|
|
if (!loader->desktop_ctx) {
|
|
|
|
|
goto err_desktop_ctx;
|
|
|
|
|
}
|
|
|
|
|
loader->icon_ctx = sfdo_icon_ctx_create(basedir_ctx);
|
|
|
|
|
if (!loader->icon_ctx) {
|
|
|
|
|
goto err_icon_ctx;
|
|
|
|
|
}
|
|
|
|
|
loader->desktop_db = sfdo_desktop_db_load(loader->desktop_ctx, NULL);
|
|
|
|
|
if (!loader->desktop_db) {
|
|
|
|
|
goto err_desktop_db;
|
|
|
|
|
}
|
|
|
|
|
loader->icon_theme = sfdo_icon_theme_load(loader->icon_ctx,
|
|
|
|
|
rc.icon_theme_name, SFDO_ICON_THEME_LOAD_OPTIONS_DEFAULT);
|
|
|
|
|
if (!loader->icon_theme) {
|
|
|
|
|
goto err_icon_theme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* basedir_ctx is not referenced by other objects */
|
|
|
|
|
sfdo_basedir_ctx_destroy(basedir_ctx);
|
|
|
|
|
|
|
|
|
|
server->icon_loader = loader;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
err_icon_theme:
|
|
|
|
|
sfdo_desktop_db_destroy(loader->desktop_db);
|
|
|
|
|
err_desktop_db:
|
|
|
|
|
sfdo_icon_ctx_destroy(loader->icon_ctx);
|
|
|
|
|
err_icon_ctx:
|
|
|
|
|
sfdo_desktop_ctx_destroy(loader->desktop_ctx);
|
|
|
|
|
err_desktop_ctx:
|
|
|
|
|
sfdo_basedir_ctx_destroy(basedir_ctx);
|
|
|
|
|
err_basedir_ctx:
|
|
|
|
|
free(loader);
|
|
|
|
|
wlr_log(WLR_ERROR, "Failed to initialize icon loader");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
icon_loader_finish(struct server *server)
|
|
|
|
|
{
|
|
|
|
|
struct icon_loader *loader = server->icon_loader;
|
|
|
|
|
if (!loader) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sfdo_desktop_db_destroy(loader->desktop_db);
|
|
|
|
|
sfdo_icon_ctx_destroy(loader->icon_ctx);
|
|
|
|
|
sfdo_desktop_ctx_destroy(loader->desktop_ctx);
|
|
|
|
|
free(loader);
|
|
|
|
|
server->icon_loader = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-28 11:20:28 +01:00
|
|
|
struct icon_ctx {
|
|
|
|
|
char *path;
|
|
|
|
|
enum sfdo_icon_file_format format;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return 0 on success and -1 on error
|
|
|
|
|
* The calling function is responsible for free()ing ctx->path
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
process_rel_name(struct icon_ctx *ctx, const char *icon_name,
|
|
|
|
|
struct icon_loader *loader, int size, int scale)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
int lookup_options = SFDO_ICON_THEME_LOOKUP_OPTIONS_DEFAULT;
|
|
|
|
|
#if !HAVE_RSVG
|
|
|
|
|
lookup_options |= SFDO_ICON_THEME_LOOKUP_OPTION_NO_SVG;
|
|
|
|
|
#endif
|
|
|
|
|
struct sfdo_icon_file *icon_file = sfdo_icon_theme_lookup(
|
|
|
|
|
loader->icon_theme, icon_name, SFDO_NT, size, scale,
|
|
|
|
|
lookup_options);
|
|
|
|
|
if (!icon_file || icon_file == SFDO_ICON_FILE_INVALID) {
|
|
|
|
|
ret = -1;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
ctx->path = xstrdup(sfdo_icon_file_get_path(icon_file, NULL));
|
|
|
|
|
ctx->format = sfdo_icon_file_get_format(icon_file);
|
|
|
|
|
out:
|
|
|
|
|
sfdo_icon_file_destroy(icon_file);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
process_abs_name(struct icon_ctx *ctx, const char *icon_name)
|
|
|
|
|
{
|
|
|
|
|
wlr_log(WLR_ERROR, "absolute paths not yet supported");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-06 17:00:40 +09:00
|
|
|
struct lab_data_buffer *
|
|
|
|
|
icon_loader_lookup(struct server *server, const char *app_id, int size, int scale)
|
|
|
|
|
{
|
|
|
|
|
struct icon_loader *loader = server->icon_loader;
|
|
|
|
|
if (!loader) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *icon_name = NULL;
|
|
|
|
|
struct sfdo_desktop_entry *entry = sfdo_desktop_db_get_entry_by_id(
|
|
|
|
|
loader->desktop_db, app_id, SFDO_NT);
|
|
|
|
|
if (entry) {
|
|
|
|
|
icon_name = sfdo_desktop_entry_get_icon(entry, NULL);
|
|
|
|
|
}
|
2024-09-28 11:20:28 +01:00
|
|
|
|
|
|
|
|
struct icon_ctx ctx = {0};
|
|
|
|
|
int ret;
|
2024-09-06 17:00:40 +09:00
|
|
|
if (!icon_name) {
|
|
|
|
|
/* fall back to app id */
|
2024-09-28 11:20:28 +01:00
|
|
|
ret = process_rel_name(&ctx, app_id, loader, size, scale);
|
|
|
|
|
} else if (icon_name[0] == '/') {
|
|
|
|
|
ret = process_abs_name(&ctx, icon_name);
|
|
|
|
|
} else {
|
|
|
|
|
/* this should be the case for most icons */
|
|
|
|
|
ret = process_rel_name(&ctx, icon_name, loader, size, scale);
|
2024-09-06 17:00:40 +09:00
|
|
|
}
|
2024-09-28 11:20:28 +01:00
|
|
|
if (ret < 0) {
|
2024-09-06 17:00:40 +09:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct lab_data_buffer *icon_buffer = NULL;
|
|
|
|
|
|
2024-09-28 11:20:28 +01:00
|
|
|
wlr_log(WLR_DEBUG, "loading icon file %s", ctx.path);
|
2024-09-06 17:00:40 +09:00
|
|
|
|
2024-09-28 11:20:28 +01:00
|
|
|
switch (ctx.format) {
|
2024-09-06 17:00:40 +09:00
|
|
|
case SFDO_ICON_FILE_FORMAT_PNG:
|
2024-09-28 11:20:28 +01:00
|
|
|
img_png_load(ctx.path, &icon_buffer);
|
2024-09-06 17:00:40 +09:00
|
|
|
break;
|
|
|
|
|
case SFDO_ICON_FILE_FORMAT_SVG:
|
|
|
|
|
#if HAVE_RSVG
|
2024-09-28 11:20:28 +01:00
|
|
|
img_svg_load(ctx.path, &icon_buffer, size * scale);
|
2024-09-06 17:00:40 +09:00
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
case SFDO_ICON_FILE_FORMAT_XPM:
|
|
|
|
|
/* XPM is not supported */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-28 11:20:28 +01:00
|
|
|
free(ctx.path);
|
2024-09-06 17:00:40 +09:00
|
|
|
return icon_buffer;
|
|
|
|
|
}
|