diff --git a/.gitignore b/.gitignore index 5e4f977..339fad0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,3 @@ src/wlr-layer-shell-unstable-v1.c # Ignore test stuff that I create to... test stuff. test_* -*.jpg -*.conf diff --git a/Makefile b/Makefile index 2d08a64..64aaaf8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PROJECT_NAME = chroma -VERSION = 1.0.1 +VERSION = 1.0.0 # Directories SRCDIR = src @@ -69,7 +69,7 @@ $(INCDIR): @mkdir -p $(INCDIR) # Build main executable -$(TARGET): version-header $(PROTOCOL_HEADERS) $(OBJECTS) | $(BINDIR) +$(TARGET): $(PROTOCOL_HEADERS) $(OBJECTS) | $(BINDIR) @echo " LINK $@" @$(CC) $(OBJECTS) -o $@ $(LDFLAGS) @@ -110,16 +110,6 @@ uninstall: rm -f $(DESTDIR)$(SYSTEMD_INSTALL)/$(PROJECT_NAME).service @echo "Uninstall complete." -# Create version header -version-header: - @echo "Generating version header..." - @echo "#ifndef CHROMA_VERSION_H" > $(INCDIR)/chroma_version.h - @echo "#define CHROMA_VERSION_H" >> $(INCDIR)/chroma_version.h - @echo "" >> $(INCDIR)/chroma_version.h - @echo "#define CHROMA_VERSION \"$(VERSION)\"" >> $(INCDIR)/chroma_version.h - @echo "" >> $(INCDIR)/chroma_version.h - @echo "#endif // CHROMA_VERSION_H" >> $(INCDIR)/chroma_version.h - # Create systemd service file systemd-service: $(SYSTEMD_DIR)/$(PROJECT_NAME).service @@ -150,68 +140,33 @@ test: $(TARGET) @echo "Running tests..." @echo "Tests not implemented yet." -# Version management targets -bump-patch: - @echo "Bumping patch version..." - @$(eval NEW_VERSION := $(shell echo $(VERSION) | awk -F. '{print $$1"."$$2"."$$3+1}')) - @sed -i 's/^VERSION = .*/VERSION = $(NEW_VERSION)/' Makefile - @echo "Version bumped to $(NEW_VERSION)" - -bump-minor: - @echo "Bumping minor version..." - @$(eval NEW_VERSION := $(shell echo $(VERSION) | awk -F. '{print $$1"."$$2+1".0"}')) - @sed -i 's/^VERSION = .*/VERSION = $(NEW_VERSION)/' Makefile - @echo "Version bumped to $(NEW_VERSION)" - -bump-major: - @echo "Bumping major version..." - @$(eval NEW_VERSION := $(shell echo $(VERSION) | awk -F. '{print $$1+1".0.0"}')) - @sed -i 's/^VERSION = .*/VERSION = $(NEW_VERSION)/' Makefile - @echo "Version bumped to $(NEW_VERSION)" - -set-version: - @if [ -z "$(NEW_VER)" ]; then \ - echo "Usage: make set-version NEW_VER=X.Y.Z"; \ - exit 1; \ - fi - @echo "Setting version to $(NEW_VER)..." - @sed -i 's/^VERSION = .*/VERSION = $(NEW_VER)/' Makefile - @echo "Version set to $(NEW_VER)" - # Help target help: @echo "Available targets:" - @echo " all - Build main executable (default)" + @echo " all - Build the main executable (default)" @echo " debug - Build with debug symbols and sanitizers" @echo " static - Build statically linked executable" @echo " check-deps - Check if all dependencies are available" - @echo " install - Install executable and systemd service" + @echo " install - Install the executable and systemd service" @echo " uninstall - Remove installed files" @echo " clean - Remove build artifacts" @echo " distclean - Remove all generated files" @echo " format - Format source code (requires clang-format)" @echo " analyze - Run static analysis (requires cppcheck)" @echo " test - Run tests" - @echo " version-header - Generate version header from Makefile" - @echo " bump-patch - Increment patch version (X.Y.Z+1)" - @echo " bump-minor - Increment minor version (X.Y+1.0)" - @echo " bump-major - Increment major version (X+1.0.0)" - @echo " set-version - Set specific version (use NEW_VER=X.Y.Z)" @echo " help - Show this help message" @echo "" @echo "Examples:" - @echo " make # Build with default settings" - @echo " make debug # Build debug version" - @echo " make PREFIX=/usr install # Install to /usr instead of /usr/local" - @echo " make CC=clang # Use clang instead of gcc" - @echo " make bump-patch # Bump to 1.0.2" - @echo " make set-version NEW_VER=2.0.0 # Set to 2.0.0" + @echo " make # Build with default settings" + @echo " make debug # Build debug version" + @echo " make PREFIX=/usr install # Install to /usr instead of /usr/local" + @echo " make CC=clang # Use clang instead of gcc" # Include dependency files -include $(DEPENDS) # Phony targets -.PHONY: all debug static check-deps install uninstall systemd-service version-header sample-config clean distclean format analyze test help bump-patch bump-minor bump-major set-version +.PHONY: all debug static check-deps install uninstall systemd-service sample-config clean distclean format analyze test help # Print variables print-%: diff --git a/include/chroma.h b/include/chroma.h index eee298a..397041f 100644 --- a/include/chroma.h +++ b/include/chroma.h @@ -12,8 +12,7 @@ #include #include -#include "chroma_version.h" - +#define CHROMA_VERSION "1.0.0" #define MAX_OUTPUTS 16 #define MAX_PATH_LEN 4096 #define CONFIG_FILE_NAME "chroma.conf" @@ -36,22 +35,6 @@ typedef enum { CHROMA_ERROR_MEMORY = -6 } chroma_error_t; -// Scaling modes for wallpaper display -typedef enum { - CHROMA_SCALE_FILL = 0, // fill entire output, crop if necessary - CHROMA_SCALE_FIT = 1, // fit image within output, add borders if needed - CHROMA_SCALE_STRETCH = 2, // stretch to fill output, may distort aspect ratio - CHROMA_SCALE_CENTER = 3 // center image at original size -} chroma_scale_mode_t; - -// Image filtering quality settings -typedef enum { - CHROMA_FILTER_NEAREST = 0, // nearest neighbor filtering (pixelated) - CHROMA_FILTER_LINEAR = 1, // linear filtering (smooth) - CHROMA_FILTER_BILINEAR = 2, // bilinear filtering (smoother) - CHROMA_FILTER_TRILINEAR = 3 // trilinear filtering (smoothest) -} chroma_filter_quality_t; - // Image data structure typedef struct { unsigned char *data; // RGBA pixel data @@ -87,11 +70,6 @@ typedef struct { // Associated wallpaper chroma_image_t *image; - // Configuration for this output - chroma_scale_mode_t scale_mode; - chroma_filter_quality_t filter_quality; - bool config_loaded; - // OpenGL resource cache GLuint texture_id; GLuint shader_program; @@ -105,8 +83,6 @@ typedef struct { typedef struct { char output_name[256]; char image_path[MAX_PATH_LEN]; - chroma_scale_mode_t scale_mode; - chroma_filter_quality_t filter_quality; } chroma_config_mapping_t; // Application configuration @@ -115,10 +91,6 @@ typedef struct { int mapping_count; char default_image[MAX_PATH_LEN]; bool daemon_mode; - - // Global scaling and filtering settings (used as defaults) - chroma_scale_mode_t default_scale_mode; - chroma_filter_quality_t default_filter_quality; } chroma_config_t; // Main application state @@ -221,11 +193,6 @@ 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); -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); -int chroma_config_create_sample(const char *config_file); -void chroma_config_print(const chroma_config_t *config); // Main loop and events int chroma_run(chroma_state_t *state); diff --git a/include/chroma_version.h b/include/chroma_version.h deleted file mode 100644 index 1ab736b..0000000 --- a/include/chroma_version.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CHROMA_VERSION_H -#define CHROMA_VERSION_H - -#ifndef CHROMA_VERSION -#define CHROMA_VERSION "1.0.1" -#endif - -#endif // CHROMA_VERSION_H diff --git a/src/config.c b/src/config.c index 6dde3b1..5fcbc9e 100644 --- a/src/config.c +++ b/src/config.c @@ -52,81 +52,11 @@ static bool parse_bool(const char *value) { return false; } -// Parse scaling mode from string -static chroma_scale_mode_t parse_scale_mode(const char *value) { - if (!value) - return CHROMA_SCALE_FILL; // default - - if (strcasecmp(value, "fill") == 0) { - return CHROMA_SCALE_FILL; - } else if (strcasecmp(value, "fit") == 0) { - return CHROMA_SCALE_FIT; - } else if (strcasecmp(value, "stretch") == 0) { - return CHROMA_SCALE_STRETCH; - } else if (strcasecmp(value, "center") == 0) { - return CHROMA_SCALE_CENTER; - } - - chroma_log("WARN", "Unknown scaling mode: %s (using fill)", value); - return CHROMA_SCALE_FILL; -} - -// Parse filter quality from string -static chroma_filter_quality_t parse_filter_quality(const char *value) { - if (!value) - return CHROMA_FILTER_LINEAR; // default - - if (strcasecmp(value, "nearest") == 0) { - return CHROMA_FILTER_NEAREST; - } else if (strcasecmp(value, "linear") == 0) { - return CHROMA_FILTER_LINEAR; - } else if (strcasecmp(value, "bilinear") == 0) { - return CHROMA_FILTER_BILINEAR; - } else if (strcasecmp(value, "trilinear") == 0) { - return CHROMA_FILTER_TRILINEAR; - } - - chroma_log("WARN", "Unknown filter quality: %s (using linear)", value); - return CHROMA_FILTER_LINEAR; -} - -// Get string representation of scaling mode -static const char *scale_mode_to_string(chroma_scale_mode_t mode) { - switch (mode) { - case CHROMA_SCALE_FILL: - return "fill"; - case CHROMA_SCALE_FIT: - return "fit"; - case CHROMA_SCALE_STRETCH: - return "stretch"; - case CHROMA_SCALE_CENTER: - return "center"; - default: - return "unknown"; - } -} - -// Get string representation of filter quality -static const char *filter_quality_to_string(chroma_filter_quality_t quality) { - switch (quality) { - case CHROMA_FILTER_NEAREST: - return "nearest"; - case CHROMA_FILTER_LINEAR: - return "linear"; - case CHROMA_FILTER_BILINEAR: - return "bilinear"; - case CHROMA_FILTER_TRILINEAR: - return "trilinear"; - default: - return "unknown"; - } -} +// Parse integer value from string // Output-to-image mapping static int add_output_mapping(chroma_config_t *config, const char *output_name, - const char *image_path, - chroma_scale_mode_t scale_mode, - chroma_filter_quality_t filter_quality) { + const char *image_path) { if (!config || !output_name || !image_path) { return CHROMA_ERROR_INIT; } @@ -137,36 +67,20 @@ static int add_output_mapping(chroma_config_t *config, const char *output_name, return CHROMA_ERROR_MEMORY; } - // Validate string lengths to prevent buffer overflow - size_t output_len = strlen(output_name); - size_t path_len = strlen(image_path); - - if (output_len >= sizeof(config->mappings[0].output_name)) { - chroma_log("ERROR", "Output name too long: %s (max %zu)", output_name, - sizeof(config->mappings[0].output_name) - 1); - return CHROMA_ERROR_CONFIG; - } - - if (path_len >= sizeof(config->mappings[0].image_path)) { - chroma_log("ERROR", "Image path too long: %s (max %zu)", image_path, - sizeof(config->mappings[0].image_path) - 1); - return CHROMA_ERROR_CONFIG; - } - chroma_config_mapping_t *mapping = &config->mappings[config->mapping_count]; - strcpy(mapping->output_name, output_name); - strcpy(mapping->image_path, image_path); - mapping->scale_mode = scale_mode; - mapping->filter_quality = filter_quality; + strncpy(mapping->output_name, output_name, sizeof(mapping->output_name) - 1); + mapping->output_name[sizeof(mapping->output_name) - 1] = '\0'; + + strncpy(mapping->image_path, image_path, sizeof(mapping->image_path) - 1); + mapping->image_path[sizeof(mapping->image_path) - 1] = '\0'; config->mapping_count++; - chroma_log("DEBUG", "Added mapping: %s -> %s (scale: %s, filter: %s)", - output_name, image_path, scale_mode_to_string(scale_mode), - filter_quality_to_string(filter_quality)); + chroma_log("DEBUG", "Added mapping: %s -> %s", output_name, image_path); chroma_log("TRACE", "Output mapping %d: '%s' -> '%s' (path length: %zu)", - config->mapping_count, output_name, image_path, path_len); + config->mapping_count, output_name, image_path, + strlen(image_path)); return CHROMA_OK; } @@ -180,10 +94,6 @@ static void init_default_config(chroma_config_t *config) { config->daemon_mode = false; config->mapping_count = 0; - // Set default scaling and filtering - config->default_scale_mode = CHROMA_SCALE_FILL; - config->default_filter_quality = CHROMA_FILTER_LINEAR; - // Set default image path (can be overridden) const char *home = getenv("HOME"); if (home) { @@ -228,29 +138,11 @@ static int parse_config_line(chroma_config_t *config, char *line, // Parse configuration options if (strcasecmp(key, "default_image") == 0) { - char *expanded_path = chroma_expand_path(value); - const char *path_to_use = expanded_path ? expanded_path : value; - size_t path_len = strlen(path_to_use); - - if (path_len >= sizeof(config->default_image)) { - chroma_log("ERROR", "Default image path too long: %s (max %zu)", - path_to_use, sizeof(config->default_image) - 1); - if (expanded_path) { - free(expanded_path); - } - return CHROMA_ERROR_CONFIG; - } - - strcpy(config->default_image, path_to_use); - - if (expanded_path) { - chroma_log("DEBUG", "Set default image: %s -> %s", value, expanded_path); - chroma_log("TRACE", "Default image path set: length=%zu, expanded='%s'", - path_len, expanded_path); - free(expanded_path); - } else { - chroma_log("WARN", "Failed to expand path, using original: %s", value); - } + strncpy(config->default_image, value, sizeof(config->default_image) - 1); + config->default_image[sizeof(config->default_image) - 1] = '\0'; + chroma_log("DEBUG", "Set default image: %s", value); + chroma_log("TRACE", "Default image path set: length=%zu, expanded='%s'", + strlen(value), value); } else if (strcasecmp(key, "daemon") == 0 || strcasecmp(key, "daemon_mode") == 0) { config->daemon_mode = parse_bool(value); @@ -259,23 +151,6 @@ static int parse_config_line(chroma_config_t *config, char *line, chroma_log("TRACE", "Daemon mode configuration: key='%s', value='%s', parsed=%s", key, value, config->daemon_mode ? "true" : "false"); - } else if (strcasecmp(key, "scale_mode") == 0 || - strcasecmp(key, "default_scale_mode") == 0) { - config->default_scale_mode = parse_scale_mode(value); - chroma_log("DEBUG", "Set default scale mode: %s", - scale_mode_to_string(config->default_scale_mode)); - chroma_log("TRACE", - "Scale mode configuration: key='%s', value='%s', parsed=%s", key, - value, scale_mode_to_string(config->default_scale_mode)); - } else if (strcasecmp(key, "filter_quality") == 0 || - strcasecmp(key, "default_filter_quality") == 0) { - config->default_filter_quality = parse_filter_quality(value); - chroma_log("DEBUG", "Set default filter quality: %s", - filter_quality_to_string(config->default_filter_quality)); - chroma_log("TRACE", - "Filter quality configuration: key='%s', value='%s', parsed=%s", - key, value, - filter_quality_to_string(config->default_filter_quality)); } else if (strncasecmp(key, "output.", 7) == 0) { // Output-specific mapping: e.g., output.DP-1=/path/to/image.jpg const char *output_name = key + 7; @@ -285,74 +160,18 @@ static int parse_config_line(chroma_config_t *config, char *line, return CHROMA_OK; } - // Check for extended output configuration with properties - // Format: output.DP-1.scale = fill - // Format: output.DP-1.filter = linear - char *dot = strchr(output_name, '.'); - if (dot) { - // This is an output property (scale or filter) - *dot = '\0'; - const char *property = dot + 1; - - // Find existing mapping for this output - chroma_config_mapping_t *mapping = NULL; - for (int i = 0; i < config->mapping_count; i++) { - if (strcmp(config->mappings[i].output_name, output_name) == 0) { - mapping = &config->mappings[i]; - break; - } - } - - if (!mapping) { - chroma_log("WARN", "Output %s not found for property %s (line %d)", - output_name, property, line_number); - return CHROMA_OK; - } - - if (strcasecmp(property, "scale") == 0) { - mapping->scale_mode = parse_scale_mode(value); - chroma_log("DEBUG", "Set scale mode for output %s: %s", output_name, - scale_mode_to_string(mapping->scale_mode)); - } else if (strcasecmp(property, "filter") == 0) { - mapping->filter_quality = parse_filter_quality(value); - chroma_log("DEBUG", "Set filter quality for output %s: %s", output_name, - filter_quality_to_string(mapping->filter_quality)); - } else { - chroma_log("WARN", "Unknown output property: %s (line %d)", property, - line_number); - } - - return CHROMA_OK; - } - - // Expand path before validation and storage - char *expanded_path = chroma_expand_path(value); - const char *path_to_validate = expanded_path ? expanded_path : value; - // Validate image path - if (chroma_image_validate(path_to_validate) != CHROMA_OK) { - chroma_log("WARN", "Invalid image path for output %s: %s (expanded: %s)", - output_name, value, path_to_validate); - if (expanded_path) { - free(expanded_path); - } + if (chroma_image_validate(value) != CHROMA_OK) { + chroma_log("WARN", "Invalid image path for output %s: %s", output_name, + value); return CHROMA_OK; } - if (add_output_mapping(config, output_name, path_to_validate, - config->default_scale_mode, - config->default_filter_quality) != CHROMA_OK) { + if (add_output_mapping(config, output_name, value) != CHROMA_OK) { chroma_log("ERROR", "Failed to add output mapping: %s -> %s", output_name, - path_to_validate); - if (expanded_path) { - free(expanded_path); - } + value); return CHROMA_ERROR_CONFIG; } - - if (expanded_path) { - free(expanded_path); - } } else { chroma_log("WARN", "Unknown configuration key line %d: %s", line_number, key); @@ -484,37 +303,6 @@ const char *chroma_config_get_image_for_output(chroma_config_t *config, return NULL; } -// Get configuration mapping for output, including scale mode and filter -// quality -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) { - if (!config || !output_name || !scale_mode || !filter_quality) { - return CHROMA_ERROR_INIT; - } - - // Look for specific output mapping - for (int i = 0; i < config->mapping_count; i++) { - if (strcmp(config->mappings[i].output_name, output_name) == 0) { - *scale_mode = config->mappings[i].scale_mode; - *filter_quality = config->mappings[i].filter_quality; - chroma_log("DEBUG", - "Found specific mapping for output %s: scale=%s, filter=%s", - output_name, scale_mode_to_string(*scale_mode), - filter_quality_to_string(*filter_quality)); - return CHROMA_OK; - } - } - - // Return defaults if no specific mapping found - *scale_mode = config->default_scale_mode; - *filter_quality = config->default_filter_quality; - chroma_log("DEBUG", "Using defaults for output %s: scale=%s, filter=%s", - output_name, scale_mode_to_string(*scale_mode), - filter_quality_to_string(*filter_quality)); - return CHROMA_OK; -} - // Create a sample configuration file int chroma_config_create_sample(const char *config_file) { if (!config_file) { @@ -558,24 +346,14 @@ void chroma_config_print(const chroma_config_t *config) { chroma_log("INFO", "=== Configuration ==="); chroma_log("INFO", "Default image: %s", config->default_image); chroma_log("INFO", "Daemon mode: %s", config->daemon_mode ? "true" : "false"); - chroma_log("INFO", "Default scale mode: %s", - scale_mode_to_string(config->default_scale_mode)); - chroma_log("INFO", "Default filter quality: %s", - filter_quality_to_string(config->default_filter_quality)); chroma_log("INFO", "Output mappings: %d", config->mapping_count); for (int i = 0; i < config->mapping_count; i++) { - chroma_log("INFO", " %s -> %s (scale: %s, filter: %s)", - config->mappings[i].output_name, config->mappings[i].image_path, - scale_mode_to_string(config->mappings[i].scale_mode), - filter_quality_to_string(config->mappings[i].filter_quality)); + chroma_log("INFO", " %s -> %s", config->mappings[i].output_name, + config->mappings[i].image_path); chroma_log( - "TRACE", - " Mapping %d: output='%s', image='%s', scale='%s', filter='%s', " - "path_exists=%s", - i, config->mappings[i].output_name, config->mappings[i].image_path, - scale_mode_to_string(config->mappings[i].scale_mode), - filter_quality_to_string(config->mappings[i].filter_quality), + "TRACE", " Mapping %d: output='%s', image='%s', path_exists=%s", i, + config->mappings[i].output_name, config->mappings[i].image_path, chroma_path_exists(config->mappings[i].image_path) ? "yes" : "no"); } chroma_log("INFO", "===================="); diff --git a/src/core.c b/src/core.c index 63d904d..8a13255 100644 --- a/src/core.c +++ b/src/core.c @@ -103,32 +103,6 @@ static int assign_wallpaper_to_output(chroma_state_t *state, // Assign image to output output->image = image; - // Store old configuration values for comparison - chroma_scale_mode_t old_scale_mode = output->scale_mode; - chroma_filter_quality_t old_filter_quality = output->filter_quality; - bool had_config = output->config_loaded; - - // Load configuration for this output (scale mode and filter quality) - if (chroma_config_get_mapping_for_output( - &state->config, output->name ? output->name : "unknown", - &output->scale_mode, &output->filter_quality) == CHROMA_OK) { - output->config_loaded = true; - chroma_log("DEBUG", "Loaded config for output %u: scale=%d, filter=%d", - output->id, output->scale_mode, output->filter_quality); - - // Check if configuration changed and invalidate texture if needed - if (had_config && (old_scale_mode != output->scale_mode || - old_filter_quality != output->filter_quality)) { - chroma_output_invalidate_texture(output); - chroma_log("DEBUG", - "Configuration changed for output %u, invalidated texture", - output->id); - } - } else { - output->config_loaded = false; - chroma_log("WARN", "Failed to load config for output %u", output->id); - } - // Create surface if it doesn't exist if (!output->surface) { int ret = chroma_surface_create(state, output); diff --git a/src/image.c b/src/image.c index 6a22991..53e03d8 100644 --- a/src/image.c +++ b/src/image.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "../include/chroma.h" diff --git a/src/render.c b/src/render.c index be9f98a..b73e1ab 100644 --- a/src/render.c +++ b/src/render.c @@ -8,146 +8,6 @@ #include "../include/chroma.h" #include "../include/stb_image.h" -// Convert filter quality enum to OpenGL parameters -static void get_gl_filter_params(chroma_filter_quality_t quality, - GLint *min_filter, GLint *mag_filter) { - switch (quality) { - case CHROMA_FILTER_NEAREST: - *min_filter = GL_NEAREST; - *mag_filter = GL_NEAREST; - break; - case CHROMA_FILTER_LINEAR: - *min_filter = GL_LINEAR; - *mag_filter = GL_LINEAR; - break; - case CHROMA_FILTER_BILINEAR: - *min_filter = GL_LINEAR_MIPMAP_LINEAR; - *mag_filter = GL_LINEAR; - break; - case CHROMA_FILTER_TRILINEAR: - *min_filter = GL_LINEAR_MIPMAP_LINEAR; - *mag_filter = GL_LINEAR; - break; - default: - *min_filter = GL_LINEAR; - *mag_filter = GL_LINEAR; - break; - } -} - -// Calculate texture coordinates based on scaling mode -static void calculate_texture_coords(chroma_scale_mode_t scale_mode, - int image_width, int image_height, - int output_width, int output_height, - float tex_coords[8]) { - // Default texture coordinates (full texture) - float u1 = 0.0f, v1 = 0.0f; // top-left - float u2 = 1.0f, v2 = 1.0f; // bottom-right - - switch (scale_mode) { - case CHROMA_SCALE_STRETCH: - // Use full texture, stretch to fit - u1 = 0.0f; - v1 = 0.0f; - u2 = 1.0f; - v2 = 1.0f; - break; - - case CHROMA_SCALE_CENTER: - // Center image at original size - // Calculate how much of the texture to show - { - float image_aspect = (float)image_width / image_height; - float output_aspect = (float)output_width / output_height; - - if (image_aspect > output_aspect) { - // Image is wider - fit width, show center portion vertically - float visible_height = (float)image_width / output_aspect; - float v_offset = - (image_height - visible_height) / (2.0f * image_height); - u1 = 0.0f; - v1 = v_offset; - u2 = 1.0f; - v2 = 1.0f - v_offset; - } else { - // Image is taller - fit height, show center portion horizontally - float visible_width = (float)image_height * output_aspect; - float u_offset = (image_width - visible_width) / (2.0f * image_width); - u1 = u_offset; - v1 = 0.0f; - u2 = 1.0f - u_offset; - v2 = 1.0f; - } - } - break; - - case CHROMA_SCALE_FIT: - // Fit image within output, maintaining aspect ratio - { - float image_aspect = (float)image_width / image_height; - float output_aspect = (float)output_width / output_height; - - if (image_aspect > output_aspect) { - // Image is wider - fit width, add borders top/bottom - float scaled_height = (float)output_width / image_aspect; - float v_border = - (output_height - scaled_height) / (2.0f * output_height); - u1 = 0.0f; - v1 = v_border; - u2 = 1.0f; - v2 = 1.0f - v_border; - } else { - // Image is taller - fit height, add borders left/right - float scaled_width = (float)output_height * image_aspect; - float u_border = (output_width - scaled_width) / (2.0f * output_width); - u1 = u_border; - v1 = 0.0f; - u2 = 1.0f - u_border; - v2 = 1.0f; - } - } - break; - - case CHROMA_SCALE_FILL: - default: - // Fill entire output, crop if necessary - { - float image_aspect = (float)image_width / image_height; - float output_aspect = (float)output_width / output_height; - - if (image_aspect > output_aspect) { - // Image is wider - crop left/right - float crop_width = image_height * output_aspect; - float u_crop = (image_width - crop_width) / (2.0f * image_width); - u1 = u_crop; - v1 = 0.0f; - u2 = 1.0f - u_crop; - v2 = 1.0f; - } else { - // Image is taller - crop top/bottom - float crop_height = image_width / output_aspect; - float v_crop = (image_height - crop_height) / (2.0f * image_height); - u1 = 0.0f; - v1 = v_crop; - u2 = 1.0f; - v2 = 1.0f - v_crop; - } - } - break; - } - - // Set texture coordinates for quad (bottom-left, bottom-right, top-right, - // top-left) - tex_coords[0] = u1; - tex_coords[1] = v2; // bottom-left - tex_coords[2] = u2; - tex_coords[3] = v2; // bottom-right - tex_coords[4] = u2; - tex_coords[5] = v1; // top-right - tex_coords[6] = u1; - tex_coords[7] = v1; // top-left -} - // Vertex shader for simple texture rendering static const char *vertex_shader_source = "#version 120\n" @@ -265,7 +125,7 @@ static int init_gl_resources(chroma_output_t *output) { glGenBuffers(1, &output->ebo); glBindBuffer(GL_ARRAY_BUFFER, output->vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, output->ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, @@ -280,8 +140,7 @@ static int init_gl_resources(chroma_output_t *output) { // Create or update texture from image data static int update_texture_from_image(chroma_output_t *output, - chroma_image_t *image, - chroma_filter_quality_t filter_quality) { + chroma_image_t *image) { if (!output || !image || !image->loaded) { return CHROMA_ERROR_INIT; } @@ -321,12 +180,8 @@ static int update_texture_from_image(chroma_output_t *output, // Set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // Use configured filter quality - GLint min_filter, mag_filter; - get_gl_filter_params(filter_quality, &min_filter, &mag_filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Upload texture data (always RGBA now) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->width, image->height, 0, @@ -648,8 +503,7 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) { } if (output->texture_id == 0) { - if (update_texture_from_image(output, output->image, - output->filter_quality) != CHROMA_OK) { + if (update_texture_from_image(output, output->image) != CHROMA_OK) { chroma_log("ERROR", "Failed to update texture for output %u", output->id); return CHROMA_ERROR_EGL; } @@ -670,25 +524,8 @@ int chroma_render_wallpaper(chroma_state_t *state, chroma_output_t *output) { glBindTexture(GL_TEXTURE_2D, output->texture_id); glUniform1i(glGetUniformLocation(output->shader_program, "texture"), 0); - // Calculate texture coordinates based on scaling mode - float tex_coords[8]; - calculate_texture_coords(output->scale_mode, output->image->width, - output->image->height, output->width, output->height, - tex_coords); - - // Create dynamic vertex data with calculated texture coordinates - float dynamic_vertices[] = { - // Position Texcoord - -1.0f, -1.0f, tex_coords[0], tex_coords[1], // bottom-left - 1.0f, -1.0f, tex_coords[2], tex_coords[3], // bottom-right - 1.0f, 1.0f, tex_coords[4], tex_coords[5], // top-right - -1.0f, 1.0f, tex_coords[6], tex_coords[7] // top-left - }; - - // Update VBO with dynamic texture coordinates + // Use cached VBO/EBO glBindBuffer(GL_ARRAY_BUFFER, output->vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(dynamic_vertices), - dynamic_vertices); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, output->ebo); // Set vertex attributes diff --git a/src/utils.c b/src/utils.c index 5341c5b..8b66fd3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -94,138 +94,18 @@ void chroma_cleanup_signals(void) { g_config_file = NULL; } -// Expand environment variables in a string -static char *expand_env_vars(const char *str) { - if (!str || strchr(str, '$') == NULL) { - return strdup(str); - } - - char *result = strdup(""); - if (!result) { - return NULL; - } - - const char *p = str; - while (*p) { - if (*p == '$') { - p++; - if (*p == '{') { - // ${VAR} format - p++; - const char *end = strchr(p, '}'); - if (!end) { - // No closing brace, treat as literal - char *tmp = realloc(result, strlen(result) + 2); - if (!tmp) { - free(result); - return NULL; - } - result = tmp; - strcat(result, "${"); - break; - } - - size_t var_len = end - p; - char *var_name = malloc(var_len + 1); - if (!var_name) { - free(result); - return NULL; - } - strncpy(var_name, p, var_len); - var_name[var_len] = '\0'; - - const char *var_value = getenv(var_name); - if (var_value) { - char *tmp = realloc(result, strlen(result) + strlen(var_value) + 1); - if (!tmp) { - free(var_name); - free(result); - return NULL; - } - result = tmp; - strcat(result, var_value); - } - - free(var_name); - p = end + 1; - } else { - // $VAR format - const char *start = p; - while (*p && (isalnum((unsigned char)*p) || *p == '_')) { - p++; - } - - if (p == start) { - // Not a valid variable name, treat $ as literal - char *tmp = realloc(result, strlen(result) + 2); - if (!tmp) { - free(result); - return NULL; - } - result = tmp; - strcat(result, "$"); - } else { - size_t var_len = p - start; - char *var_name = malloc(var_len + 1); - if (!var_name) { - free(result); - return NULL; - } - strncpy(var_name, start, var_len); - var_name[var_len] = '\0'; - - const char *var_value = getenv(var_name); - if (var_value) { - char *tmp = realloc(result, strlen(result) + strlen(var_value) + 1); - if (!tmp) { - free(var_name); - free(result); - return NULL; - } - result = tmp; - strcat(result, var_value); - } - - free(var_name); - } - } - } else { - // Regular character - size_t len = strlen(result); - char *tmp = realloc(result, len + 2); - if (!tmp) { - free(result); - return NULL; - } - result = tmp; - result[len] = *p; - result[len + 1] = '\0'; - p++; - } - } - - return result; -} - -// Expand tilde and environment variables in path +// Expand tilde in path char *chroma_expand_path(const char *path) { if (!path) { return NULL; } - // First expand environment variables - char *env_expanded = expand_env_vars(path); - if (!env_expanded) { - return NULL; - } - - // Then expand tilde if present - if (env_expanded[0] != '~') { - return env_expanded; + if (path[0] != '~') { + return strdup(path); } const char *home; - if (env_expanded[1] == '/' || env_expanded[1] == '\0') { + if (path[1] == '/' || path[1] == '\0') { // ~/... or just ~ home = getenv("HOME"); if (!home) { @@ -236,39 +116,34 @@ char *chroma_expand_path(const char *path) { } if (!home) { chroma_log("ERROR", "Could not determine home directory"); - free(env_expanded); return strdup(path); // Return original path as fallback } size_t home_len = strlen(home); - size_t path_len = strlen(env_expanded); + size_t path_len = strlen(path); char *expanded = malloc(home_len + path_len); // -1 for ~ +1 for \0 if (!expanded) { chroma_log("ERROR", "Failed to allocate memory for path expansion"); - free(env_expanded); return strdup(path); } strcpy(expanded, home); - if (env_expanded[1] == '/') { - strcat(expanded, env_expanded + 1); + if (path[1] == '/') { + strcat(expanded, path + 1); } - free(env_expanded); return expanded; } else { // ~user/... - const char *slash = strchr(env_expanded, '/'); - size_t user_len = - slash ? (size_t)(slash - env_expanded - 1) : strlen(env_expanded) - 1; + const char *slash = strchr(path, '/'); + size_t user_len = slash ? (size_t)(slash - path - 1) : strlen(path) - 1; char *username = malloc(user_len + 1); if (!username) { - free(env_expanded); return strdup(path); } - strncpy(username, env_expanded + 1, user_len); + strncpy(username, path + 1, user_len); username[user_len] = '\0'; struct passwd *pw = getpwnam(username); @@ -276,7 +151,6 @@ char *chroma_expand_path(const char *path) { if (!pw) { chroma_log("ERROR", "User not found: %s", username); free(username); - free(env_expanded); return strdup(path); } @@ -286,7 +160,6 @@ char *chroma_expand_path(const char *path) { size_t remaining_len = slash ? strlen(slash) : 0; char *expanded = malloc(home_len + remaining_len + 1); if (!expanded) { - free(env_expanded); return strdup(path); } @@ -295,7 +168,6 @@ char *chroma_expand_path(const char *path) { strcat(expanded, slash); } - free(env_expanded); return expanded; } } @@ -541,4 +413,4 @@ void chroma_format_memory_size(size_t bytes, char *buffer, size_t buffer_size) { } // Cleanup utility functions -void chroma_utils_cleanup(void) { chroma_cleanup_signals(); } +void chroma_utils_cleanup(void) { chroma_cleanup_signals(); } \ No newline at end of file