config: add description-based output matching with desc: prefix

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Idbe0661f0c491512d61ace4337ebe8cd6a6a6964
This commit is contained in:
raf 2026-01-31 15:23:50 +03:00
commit 459989e896
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
3 changed files with 60 additions and 18 deletions

8
include/chroma.h vendored
View file

@ -250,11 +250,13 @@ void chroma_images_cleanup(chroma_state_t *state);
int chroma_config_load(chroma_config_t *config, const char *config_file);
void chroma_config_free(chroma_config_t *config);
const char *chroma_config_get_image_for_output(chroma_config_t *config,
const char *output_name);
const char *output_name,
const char *output_description);
int chroma_config_get_mapping_for_output(
chroma_config_t *config, const char *output_name,
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality,
chroma_anchor_t *anchor, float *anchor_x, float *anchor_y);
const char *output_description, chroma_scale_mode_t *scale_mode,
chroma_filter_quality_t *filter_quality, chroma_anchor_t *anchor,
float *anchor_x, float *anchor_y);
void chroma_config_print(const chroma_config_t *config);

View file

@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "../include/chroma.h"
@ -27,6 +28,38 @@ static char *trim_whitespace(char *str) {
}
// Remove quotes from a string
// Match output name/description against a config pattern
// Supports:
// - Exact name match: "DP-1" matches wl_output.name == "DP-1"
// - Description prefix match: "desc:Samsung" matches if description starts
// with "Samsung"
static bool match_output(const char *pattern, const char *output_name,
const char *output_description) {
if (!pattern || !output_name) {
return false;
}
// Try exact name match first
if (strcmp(pattern, output_name) == 0) {
return true;
}
// Check for description prefix match: "desc:<prefix>"
if (strncmp(pattern, "desc:", 5) == 0) {
const char *desc_prefix = pattern + 5;
size_t prefix_len = strlen(desc_prefix);
if (output_description && prefix_len > 0) {
// Match if description starts with the prefix (case-insensitive)
if (strncasecmp(output_description, desc_prefix, prefix_len) == 0) {
return true;
}
}
}
return false;
}
static char *remove_quotes(char *str) {
size_t len = strlen(str);
if (len >= 2 && ((str[0] == '"' && str[len - 1] == '"') ||
@ -660,16 +693,19 @@ void chroma_config_free(chroma_config_t *config) {
// Get image path for specific output
const char *chroma_config_get_image_for_output(chroma_config_t *config,
const char *output_name) {
const char *output_name,
const char *output_description) {
if (!config || !output_name) {
return NULL;
}
// Look for specific output mapping
// Look for specific output mapping (name or description match)
for (int i = 0; i < config->mapping_count; i++) {
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
chroma_log("DEBUG", "Found specific mapping for output %s: %s",
output_name, config->mappings[i].image_path);
if (match_output(config->mappings[i].output_name, output_name,
output_description)) {
chroma_log("DEBUG", "Found specific mapping for output %s (desc: %s): %s",
output_name, output_description ? output_description : "none",
config->mappings[i].image_path);
return config->mappings[i].image_path;
}
}
@ -689,25 +725,28 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config,
// quality, anchor, and custom anchor coordinates
int chroma_config_get_mapping_for_output(
chroma_config_t *config, const char *output_name,
chroma_scale_mode_t *scale_mode, chroma_filter_quality_t *filter_quality,
chroma_anchor_t *anchor, float *anchor_x, float *anchor_y) {
const char *output_description, chroma_scale_mode_t *scale_mode,
chroma_filter_quality_t *filter_quality, chroma_anchor_t *anchor,
float *anchor_x, float *anchor_y) {
if (!config || !output_name || !scale_mode || !filter_quality || !anchor ||
!anchor_x || !anchor_y) {
return CHROMA_ERROR_INIT;
}
// Look for specific output mapping
// Look for specific output mapping (name or description match)
for (int i = 0; i < config->mapping_count; i++) {
if (strcmp(config->mappings[i].output_name, output_name) == 0) {
if (match_output(config->mappings[i].output_name, output_name,
output_description)) {
*scale_mode = config->mappings[i].scale_mode;
*filter_quality = config->mappings[i].filter_quality;
*anchor = config->mappings[i].anchor;
*anchor_x = config->mappings[i].anchor_x;
*anchor_y = config->mappings[i].anchor_y;
chroma_log("DEBUG",
"Found specific mapping for output %s: scale=%s, filter=%s, "
"anchor=%s @ %.1f,%.1f",
output_name, scale_mode_to_string(*scale_mode),
"Found specific mapping for output %s (desc: %s): scale=%s, "
"filter=%s, anchor=%s @ %.1f,%.1f",
output_name, output_description ? output_description : "none",
scale_mode_to_string(*scale_mode),
filter_quality_to_string(*filter_quality),
anchor_to_string(*anchor), *anchor_x, *anchor_y);
return CHROMA_OK;

View file

@ -77,7 +77,8 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
// Get image path for this output
const char *image_path = chroma_config_get_image_for_output(
&state->config, output->name ? output->name : "unknown");
&state->config, output->name ? output->name : "unknown",
output->description);
if (!image_path) {
chroma_log("WARN", "No wallpaper configured for output %u (%s)", output->id,
output->name ? output->name : "unknown");
@ -121,8 +122,8 @@ static int assign_wallpaper_to_output(chroma_state_t *state,
// anchor coords)
if (chroma_config_get_mapping_for_output(
&state->config, output->name ? output->name : "unknown",
&output->scale_mode, &output->filter_quality, &output->anchor,
&output->anchor_x, &output->anchor_y) == CHROMA_OK) {
output->description, &output->scale_mode, &output->filter_quality,
&output->anchor, &output->anchor_x, &output->anchor_y) == CHROMA_OK) {
output->config_loaded = true;
chroma_log("DEBUG",
"Loaded config for output %u: scale=%d, filter=%d, anchor=%d @ "