From bc77b887ad02db102d2cbdfd48dc19ad6232143d Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Tue, 30 Sep 2025 20:11:06 +0300 Subject: [PATCH] various: log memory events Signed-off-by: NotAShelf Change-Id: I6a6a69643b6d00277bb9bcfeb4cd01dc78d7cd3d --- include/chroma.h | 15 ++++++ src/config.c | 34 ++++++++++++++ src/core.c | 116 +++++++++++++++++++++++++++++++++++++++++++---- src/image.c | 15 ++++-- src/main.c | 30 ++++++++---- src/render.c | 29 ++++++++++++ src/wayland.c | 88 +++++++++++++++++++++++++---------- 7 files changed, 280 insertions(+), 47 deletions(-) diff --git a/include/chroma.h b/include/chroma.h index ba36ce5..397041f 100644 --- a/include/chroma.h +++ b/include/chroma.h @@ -17,6 +17,13 @@ #define MAX_PATH_LEN 4096 #define CONFIG_FILE_NAME "chroma.conf" +// Log levels +#define CHROMA_LOG_ERROR 0 +#define CHROMA_LOG_WARN 1 +#define CHROMA_LOG_INFO 2 +#define CHROMA_LOG_DEBUG 3 +#define CHROMA_LOG_TRACE 4 + // Error codes typedef enum { CHROMA_OK = 0, @@ -219,6 +226,14 @@ void chroma_sleep_ms(long ms); void chroma_format_memory_size(size_t bytes, char *buffer, size_t buffer_size); void chroma_utils_cleanup(void); +// Memory tracking and logging +void chroma_log_memory_stats(const char *context); +size_t chroma_get_memory_usage(void); +void chroma_log_resource_allocation(const char *resource_type, size_t size, + const char *description); +void chroma_log_resource_deallocation(const char *resource_type, size_t size, + const char *description); + // Listener structures extern const struct wl_registry_listener chroma_registry_listener_impl; extern const struct wl_output_listener chroma_output_listener_impl; diff --git a/src/config.c b/src/config.c index 7ff8cac..5fcbc9e 100644 --- a/src/config.c +++ b/src/config.c @@ -78,6 +78,9 @@ static int add_output_mapping(chroma_config_t *config, const char *output_name, config->mapping_count++; 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, + strlen(image_path)); return CHROMA_OK; } @@ -138,11 +141,16 @@ static int parse_config_line(chroma_config_t *config, char *line, 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); chroma_log("DEBUG", "Set daemon mode: %s", config->daemon_mode ? "true" : "false"); + chroma_log("TRACE", + "Daemon mode configuration: key='%s', value='%s', parsed=%s", + key, value, config->daemon_mode ? "true" : "false"); } 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; @@ -167,6 +175,8 @@ static int parse_config_line(chroma_config_t *config, char *line, } else { chroma_log("WARN", "Unknown configuration key line %d: %s", line_number, key); + chroma_log("TRACE", "Unrecognized config line %d: key='%s', value='%s'", + line_number, key, value); } return CHROMA_OK; @@ -200,6 +210,9 @@ int chroma_config_load(chroma_config_t *config, const char *config_file) { } chroma_log("INFO", "Loading configuration from: %s", config_file); + chroma_log("TRACE", + "Starting configuration parsing, estimated config size: %ld bytes", + chroma_get_file_size(config_file)); char line[1024]; int line_number = 0; @@ -229,6 +242,14 @@ int chroma_config_load(chroma_config_t *config, const char *config_file) { "Loaded configuration: %d output mappings, default image: %s", config->mapping_count, config->default_image); + // Log configuration memory usage + size_t config_size = + sizeof(chroma_config_t) + + (config->mapping_count * sizeof(chroma_config_mapping_t)); + chroma_log_resource_allocation("config_data", config_size, + "configuration structure"); + chroma_log_memory_stats("post-config-load"); + return CHROMA_OK; } @@ -238,6 +259,15 @@ void chroma_config_free(chroma_config_t *config) { return; } + // Log configuration deallocation + size_t config_size = + sizeof(chroma_config_t) + + (config->mapping_count * sizeof(chroma_config_mapping_t)); + chroma_log_resource_deallocation("config_data", config_size, + "configuration structure"); + + chroma_log("TRACE", "Clearing %d output mappings from configuration", + config->mapping_count); memset(config->mappings, 0, sizeof(config->mappings)); config->mapping_count = 0; @@ -321,6 +351,10 @@ void chroma_config_print(const chroma_config_t *config) { for (int i = 0; i < config->mapping_count; i++) { chroma_log("INFO", " %s -> %s", config->mappings[i].output_name, config->mappings[i].image_path); + chroma_log( + "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 f07b8ee..8a13255 100644 --- a/src/core.c +++ b/src/core.c @@ -9,8 +9,8 @@ #include "../include/chroma.h" -// Global logging level -static int log_level = 0; // 0=ERROR, 1=WARN, 2=INFO, 3=DEBUG +// Global logging level (using CHROMA_LOG_* constants) +static int log_level = CHROMA_LOG_WARN; // Default to WARN and ERROR only // Initialize chroma state int chroma_init(chroma_state_t *state) { @@ -32,6 +32,8 @@ int chroma_init(chroma_state_t *state) { state->initialized = true; chroma_log("INFO", "Chroma state initialized"); + chroma_log_resource_allocation("chroma_state", sizeof(chroma_state_t), + "main application state"); return CHROMA_OK; } @@ -43,6 +45,7 @@ void chroma_cleanup(chroma_state_t *state) { } chroma_log("INFO", "Cleaning up chroma state"); + chroma_log_memory_stats("pre-cleanup"); // Stop the main loop state->running = false; @@ -60,6 +63,8 @@ void chroma_cleanup(chroma_state_t *state) { chroma_config_free(&state->config); state->initialized = false; + chroma_log_resource_deallocation("chroma_state", sizeof(chroma_state_t), + "main application state"); chroma_log("INFO", "Chroma cleanup complete"); } @@ -116,6 +121,7 @@ static int assign_wallpaper_to_output(chroma_state_t *state, chroma_log("INFO", "Assigned wallpaper to output %u (%s): %s", output->id, output->name ? output->name : "unknown", image_path); + chroma_log_memory_stats("post-wallpaper-assignment"); return CHROMA_OK; } @@ -173,20 +179,20 @@ static int process_wayland_events(chroma_state_t *state) { return CHROMA_ERROR_WAYLAND; } - /* Dispatch pending events */ + // Dispatch pending events if (wl_display_dispatch_pending(state->display) == -1) { chroma_log("ERROR", "Failed to dispatch pending Wayland events: %s", strerror(errno)); return CHROMA_ERROR_WAYLAND; } - /* Read events from the server */ + // Read events from the server if (wl_display_read_events(state->display) == -1) { chroma_log("ERROR", "Failed to read Wayland events: %s", strerror(errno)); return CHROMA_ERROR_WAYLAND; } - /* Dispatch the read events */ + // Dispatch the read events if (wl_display_dispatch_pending(state->display) == -1) { chroma_log("ERROR", "Failed to dispatch read Wayland events: %s", strerror(errno)); @@ -203,6 +209,7 @@ int chroma_run(chroma_state_t *state) { } chroma_log("INFO", "Starting main event loop"); + chroma_log_memory_stats("main-loop-start"); state->running = true; // Initial wallpaper assignment @@ -247,7 +254,7 @@ int chroma_run(chroma_state_t *state) { FD_ZERO(&readfds); FD_SET(fd, &readfds); - timeout.tv_sec = 1; // 1 second timeout + timeout.tv_sec = 1; // 1s timeout timeout.tv_usec = 0; int select_result = select(fd + 1, &readfds, NULL, NULL, &timeout); @@ -307,24 +314,41 @@ const char *chroma_error_string(chroma_error_t error) { } } -// Logging function +// Convert log level string to numeric level +static int log_level_from_string(const char *level) { + if (strcmp(level, "ERROR") == 0) + return CHROMA_LOG_ERROR; + if (strcmp(level, "WARN") == 0) + return CHROMA_LOG_WARN; + if (strcmp(level, "INFO") == 0) + return CHROMA_LOG_INFO; + if (strcmp(level, "DEBUG") == 0) + return CHROMA_LOG_DEBUG; + if (strcmp(level, "TRACE") == 0) + return CHROMA_LOG_TRACE; + return CHROMA_LOG_ERROR; // default to ERROR for unknown levels +} + +// Logging function with level filtering void chroma_log(const char *level, const char *format, ...) { + int msg_level = log_level_from_string(level); + if (msg_level > log_level) { + return; + } + va_list args; char timestamp[32]; struct timeval tv; struct tm *tm_info; - // Get current time gettimeofday(&tv, NULL); tm_info = localtime(&tv.tv_sec); - // Format timestamp snprintf(timestamp, sizeof(timestamp), "%04d-%02d-%02d %02d:%02d:%02d.%03d", tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday, tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, (int)(tv.tv_usec / 1000)); - // Print log message printf("[%s] %s: ", timestamp, level); va_start(args, format); @@ -445,3 +469,75 @@ void chroma_get_stats(chroma_state_t *state, int *active_outputs, if (loaded_images) *loaded_images = loaded; } + +// Get current memory usage from /proc/self/status +// FIXME: some users may choose to confine /proc, we need a cleaner +// way of getting this data in the future +size_t chroma_get_memory_usage(void) { + FILE *file = fopen("/proc/self/status", "r"); + if (!file) { + return 0; + } + + size_t vm_rss = 0; + char line[256]; + + while (fgets(line, sizeof(line), file)) { + if (strncmp(line, "VmRSS:", 6) == 0) { + // Parse VmRSS line: "VmRSS: 1234 kB" + char *ptr = line + 6; + while (*ptr == ' ' || *ptr == '\t') + ptr++; // Skip whitespace + vm_rss = (size_t)strtoul(ptr, NULL, 10) * 1024; // Convert kB to bytes + break; + } + } + + fclose(file); + return vm_rss; +} + +// Log memory statistics with context +void chroma_log_memory_stats(const char *context) { + size_t memory_usage = chroma_get_memory_usage(); + char mem_str[64]; + + chroma_format_memory_size(memory_usage, mem_str, sizeof(mem_str)); + chroma_log("INFO", "Memory usage [%s]: %s", context, mem_str); +} + +// Log resource allocation +void chroma_log_resource_allocation(const char *resource_type, size_t size, + const char *description) { + if (size > 0) { + char size_str[64]; + chroma_format_memory_size(size, size_str, sizeof(size_str)); + chroma_log("DEBUG", "Allocated %s: %s (%s)", resource_type, size_str, + description); + } else { + chroma_log("DEBUG", "Allocated %s: %s", resource_type, description); + } + + // Log memory stats after significant allocations (>1MB) + if (size > 1024 * 1024) { + chroma_log_memory_stats("post-allocation"); + } +} + +// Log resource deallocation +void chroma_log_resource_deallocation(const char *resource_type, size_t size, + const char *description) { + if (size > 0) { + char size_str[64]; + chroma_format_memory_size(size, size_str, sizeof(size_str)); + chroma_log("DEBUG", "Deallocated %s: %s (%s)", resource_type, size_str, + description); + } else { + chroma_log("DEBUG", "Deallocated %s: %s", resource_type, description); + } + + // Log memory stats after significant deallocations (>1MB) + if (size > 1024 * 1024) { + chroma_log_memory_stats("post-deallocation"); + } +} diff --git a/src/image.c b/src/image.c index e267728..53e03d8 100644 --- a/src/image.c +++ b/src/image.c @@ -1,7 +1,6 @@ #define STB_IMAGE_IMPLEMENTATION #include "../include/stb_image.h" -#include #include #include #include @@ -79,10 +78,13 @@ int chroma_image_load(chroma_image_t *image, const char *path) { image->loaded = true; + // Calculate and log memory allocation + size_t image_size = (size_t)image->width * image->height * image->channels; + chroma_log_resource_allocation("image_data", image_size, path); + chroma_log("INFO", "Loaded image: %s (%dx%d, %d channels, %.2f MB)", path, image->width, image->height, image->channels, - (double)(image->width * image->height * image->channels) / - (1024.0 * 1024.0)); + (double)image_size / (1024.0 * 1024.0)); return CHROMA_OK; } @@ -94,6 +96,10 @@ void chroma_image_free(chroma_image_t *image) { } if (image->data) { + // Log memory deallocation before freeing + size_t image_size = (size_t)image->width * image->height * image->channels; + chroma_log_resource_deallocation("image_data", image_size, image->path); + // Always use stbi_image_free since we load directly with stbi_load stbi_image_free(image->data); image->data = NULL; @@ -218,12 +224,15 @@ void chroma_images_cleanup(chroma_state_t *state) { return; } + chroma_log("DEBUG", "Cleaning up %d images", state->image_count); + for (int i = 0; i < state->image_count; i++) { chroma_image_free(&state->images[i]); } state->image_count = 0; chroma_log("INFO", "Cleaned up all images"); + chroma_log_memory_stats("post-image-cleanup"); } // Preload common image formats for validation diff --git a/src/main.c b/src/main.c index d09fb42..9cbd464 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -9,7 +8,7 @@ #include "../include/chroma.h" -/* Global state for signal handling */ +// Global state for signal handling volatile sig_atomic_t chroma_should_quit = 0; static void print_usage(const char *program_name) { @@ -18,7 +17,9 @@ static void print_usage(const char *program_name) { printf("Options:\n"); printf(" -c, --config FILE Configuration file path\n"); printf(" -d, --daemon Run as daemon\n"); - printf(" -v, --verbose Verbose logging\n"); + printf(" -v, --verbose Increase verbosity (can be used multiple " + "times)\n"); + printf(" -v: INFO, -vv: DEBUG, -vvv: TRACE\n"); printf(" -h, --help Show this help\n"); printf(" --version Show version information\n"); printf("\nExamples:\n"); @@ -124,7 +125,7 @@ int main(int argc, char *argv[]) { chroma_state_t state; char *config_file = NULL; bool daemon_mode = false; - bool verbose = false; + int verbose_level = 0; int opt; int ret = 0; @@ -143,7 +144,7 @@ int main(int argc, char *argv[]) { daemon_mode = true; break; case 'v': - verbose = true; + verbose_level++; break; case 'h': print_usage(argv[0]); @@ -161,10 +162,9 @@ int main(int argc, char *argv[]) { memset(&state, 0, sizeof(state)); state.config.daemon_mode = daemon_mode; - // Set log level based on verbose flag - if (verbose) { - chroma_set_log_level(1); // Enable debug logging - } + // Set log level based on verbosity count + // 0: ERROR+WARN only, 1: +INFO, 2: +DEBUG, 3+: +TRACE + chroma_set_log_level(verbose_level); // Set up signal handlers if (setup_signals() != 0) { @@ -189,6 +189,8 @@ int main(int argc, char *argv[]) { // Initialize chroma chroma_log("INFO", "Initializing chroma wallpaper daemon v%s", CHROMA_VERSION); + chroma_log_memory_stats("startup"); + ret = chroma_init(&state); if (ret != CHROMA_OK) { chroma_log("ERROR", "Failed to initialize chroma: %s", @@ -196,6 +198,7 @@ int main(int argc, char *argv[]) { chroma_cleanup(&state); return 1; } + chroma_log_memory_stats("post-init"); // Load configuration chroma_log("INFO", "Loading configuration from: %s", config_file); @@ -203,6 +206,7 @@ int main(int argc, char *argv[]) { chroma_log("WARN", "Failed to load config file, using defaults"); // Continue with default configuration } + chroma_log_memory_stats("post-config-load"); // Connect to Wayland ret = chroma_wayland_connect(&state); @@ -212,6 +216,7 @@ int main(int argc, char *argv[]) { chroma_cleanup(&state); return 1; } + chroma_log_memory_stats("post-wayland-connect"); // Initialize EGL ret = chroma_egl_init(&state); @@ -221,18 +226,23 @@ int main(int argc, char *argv[]) { chroma_cleanup(&state); return 1; } + chroma_log_memory_stats("post-egl-init"); chroma_log("INFO", "Chroma daemon initialized successfully"); + chroma_log_memory_stats("pre-main-loop"); // Main event loop ret = chroma_run(&state); if (ret != CHROMA_OK) { chroma_log("ERROR", "Main loop failed: %s", chroma_error_string(ret)); } + chroma_log_memory_stats("post-main-loop"); // Cleanup chroma_log("INFO", "Shutting down chroma daemon"); + chroma_log_memory_stats("pre-cleanup"); chroma_cleanup(&state); + chroma_log_memory_stats("post-cleanup"); return (ret == CHROMA_OK) ? 0 : 1; -} \ No newline at end of file +} diff --git a/src/render.c b/src/render.c index dda4030..b73e1ab 100644 --- a/src/render.c +++ b/src/render.c @@ -156,6 +156,15 @@ static int update_texture_from_image(chroma_output_t *output, // Delete existing texture if it exists if (output->texture_id != 0) { + // Estimate texture size for logging + // FIXME: Unfortunately this only works if we have previous image info. + // Could this b made more accurate? + if (output->image && output->image->loaded) { + size_t texture_size = (size_t)output->image->width * + output->image->height * output->image->channels; + chroma_log_resource_deallocation("gpu_texture", texture_size, + "texture replacement"); + } glDeleteTextures(1, &output->texture_id); output->texture_id = 0; } @@ -164,6 +173,10 @@ static int update_texture_from_image(chroma_output_t *output, glGenTextures(1, &output->texture_id); glBindTexture(GL_TEXTURE_2D, output->texture_id); + // Log GPU texture allocation + size_t texture_size = (size_t)image->width * image->height * image->channels; + chroma_log_resource_allocation("gpu_texture", texture_size, image->path); + // 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); @@ -207,6 +220,9 @@ static int update_texture_from_image(chroma_output_t *output, "GPU: %s", (double)freed_bytes / (1024.0 * 1024.0), total_using, image->path); + chroma_log_resource_deallocation("image_data", freed_bytes, + "post-gpu-upload"); + chroma_log_memory_stats("post-gpu-upload"); } } @@ -222,6 +238,7 @@ static void cleanup_gl_resources(chroma_output_t *output) { } if (output->texture_id != 0) { + chroma_log_resource_deallocation("gpu_texture", 0, "cleanup"); glDeleteTextures(1, &output->texture_id); output->texture_id = 0; } @@ -296,6 +313,7 @@ int chroma_egl_init(chroma_state_t *state) { } chroma_log("INFO", "EGL initialized: version %d.%d", major, minor); + chroma_log_memory_stats("post-egl-init"); // Bind OpenGL API if (!eglBindAPI(EGL_OPENGL_API)) { @@ -420,6 +438,11 @@ int chroma_surface_create(chroma_state_t *state, chroma_output_t *output) { chroma_log("INFO", "Created surface for output %u (%dx%d)", output->id, output->width, output->height); + // Log surface creation resource allocation + size_t surface_size = + (size_t)output->width * output->height * 4; // estimate RGBA surface + chroma_log_resource_allocation("egl_surface", surface_size, "output surface"); + return CHROMA_OK; } @@ -452,6 +475,12 @@ void chroma_surface_destroy(chroma_output_t *output) { output->surface = NULL; } + // Log surface destruction + size_t surface_size = + (size_t)output->width * output->height * 4; // estimate RGBA surface + chroma_log_resource_deallocation("egl_surface", surface_size, + "output surface cleanup"); + chroma_log("DEBUG", "Destroyed surface for output %u", output->id); } diff --git a/src/wayland.c b/src/wayland.c index 157cb9d..508ec48 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -14,6 +14,7 @@ static void registry_global(void *data, struct wl_registry *registry, chroma_log("DEBUG", "Registry global: %s (id=%u, version=%u)", interface, id, version); + chroma_log("TRACE", "Checking interface binding for: %s", interface); if (strcmp(interface, wl_compositor_interface.name) == 0) { state->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, @@ -22,6 +23,7 @@ static void registry_global(void *data, struct wl_registry *registry, chroma_log("ERROR", "Failed to bind compositor"); } else { chroma_log("INFO", "Bound compositor (version %u)", version); + chroma_log("TRACE", "Compositor binding successful, interface ready"); } } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { state->layer_shell = @@ -31,6 +33,9 @@ static void registry_global(void *data, struct wl_registry *registry, chroma_log("ERROR", "Failed to bind layer shell"); } else { chroma_log("INFO", "Bound layer shell (version %u)", version); + chroma_log( + "TRACE", + "wlr-layer-shell protocol available, wallpaper support enabled"); } } else if (strcmp(interface, wl_output_interface.name) == 0) { struct wl_output *output = wl_registry_bind( @@ -52,9 +57,10 @@ static void registry_global(void *data, struct wl_registry *registry, static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t id) { chroma_state_t *state = (chroma_state_t *)data; - (void)registry; // Unused parameter + (void)registry; chroma_log("DEBUG", "Registry global remove: id=%u", id); + chroma_log("TRACE", "Global object removal initiated for id=%u", id); chroma_output_remove(state, id); } @@ -63,24 +69,31 @@ const struct wl_registry_listener chroma_registry_listener_impl = { .global_remove = registry_global_remove, }; -/* Layer surface event handlers */ +// Layer surface event handlers static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { chroma_output_t *output = (chroma_output_t *)data; - (void)layer_surface; // Unused parameter + (void)layer_surface; chroma_log("DEBUG", "Layer surface configure: %ux%u, serial=%u", width, height, serial); + chroma_log( + "TRACE", + "Configuring layer surface for output %u: dimensions=%ux%u, serial=%u", + output->id, width, height, serial); output->configure_serial = serial; - /* Acknowledge the configure event */ + // Acknowledge the configure event zwlr_layer_surface_v1_ack_configure(output->layer_surface, serial); + chroma_log("TRACE", "Sent configure acknowledgment for output %u serial %u", + output->id, serial); - /* Commit the surface to apply the acknowledgment */ + // Commit the surface to apply the acknowledgment wl_surface_commit(output->surface); + chroma_log("TRACE", "Surface committed for output %u", output->id); chroma_log("DEBUG", "Acknowledged layer surface configure for output %u", output->id); @@ -89,11 +102,11 @@ static void layer_surface_configure(void *data, static void layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *layer_surface) { chroma_output_t *output = (chroma_output_t *)data; - (void)layer_surface; /* Unused parameter */ + (void)layer_surface; chroma_log("INFO", "Layer surface closed for output %u", output->id); - /* Clean up the surface */ + // Clean up the surface if (output->surface) { chroma_surface_destroy(output); } @@ -105,17 +118,17 @@ const struct zwlr_layer_surface_v1_listener chroma_layer_surface_listener_impl = .closed = layer_surface_closed, }; -/* Output event handlers */ +// Output event handlers static void output_geometry(void *data, struct wl_output *output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; // Unused parameter - (void)subpixel; // Unused parameter - (void)make; // Unused parameter - (void)model; // Unused parameter + (void)output; + (void)subpixel; + (void)make; + (void)model; chroma_output->x = x; chroma_output->y = y; @@ -124,24 +137,36 @@ static void output_geometry(void *data, struct wl_output *output, int32_t x, chroma_log("DEBUG", "Output %u geometry: %dx%d at (%d,%d), transform=%d", chroma_output->id, physical_width, physical_height, x, y, transform); + chroma_log("TRACE", + "Output %u geometry details: physical_size=%dx%dmm, " + "position=(%d,%d), transform=%d", + chroma_output->id, physical_width, physical_height, x, y, + transform); } static void output_mode(void *data, struct wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; // Unused parameter + (void)output; if (flags & WL_OUTPUT_MODE_CURRENT) { chroma_output->width = width; chroma_output->height = height; chroma_log("DEBUG", "Output %u mode: %dx%d@%d (current)", chroma_output->id, width, height, refresh); + chroma_log("TRACE", + "Current mode set for output %u: %dx%d@%dHz, flags=0x%x", + chroma_output->id, width, height, refresh, flags); + } else { + chroma_log("TRACE", + "Non-current mode for output %u: %dx%d@%dHz, flags=0x%x", + chroma_output->id, width, height, refresh, flags); } } static void output_scale(void *data, struct wl_output *output, int32_t scale) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; // Unused parameter + (void)output; chroma_output->scale = scale; chroma_log("DEBUG", "Output %u scale: %d", chroma_output->id, scale); @@ -150,7 +175,7 @@ static void output_scale(void *data, struct wl_output *output, int32_t scale) { static void output_name(void *data, struct wl_output *output, const char *name) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; // Unused parameter + (void)output; free(chroma_output->name); chroma_output->name = strdup(name); @@ -165,7 +190,7 @@ static void output_name(void *data, struct wl_output *output, static void output_description(void *data, struct wl_output *output, const char *description) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; // Unused parameter + (void)output; free(chroma_output->description); chroma_output->description = strdup(description); @@ -180,16 +205,23 @@ static void output_description(void *data, struct wl_output *output, static void output_done(void *data, struct wl_output *output) { chroma_output_t *chroma_output = (chroma_output_t *)data; - (void)output; /* Unused parameter */ + (void)output; chroma_log("DEBUG", "Output %u done - configuration complete", chroma_output->id); + chroma_log("TRACE", + "Output %u configuration finalized: %dx%d, scale=%d, name='%s'", + chroma_output->id, chroma_output->width, chroma_output->height, + chroma_output->scale, + chroma_output->name ? chroma_output->name : "unknown"); // Mark output as active and ready for wallpaper assignment chroma_output->active = true; // Trigger wallpaper assignment for this output if (chroma_output->state) { + chroma_log("TRACE", "Triggering wallpaper assignment for output %u", + chroma_output->id); handle_output_done(chroma_output->state, chroma_output); } } @@ -203,7 +235,7 @@ const struct wl_output_listener chroma_output_listener_impl = { .done = output_done, }; -/* Wayland connection functions */ +// Wayland connection functions int chroma_wayland_connect(chroma_state_t *state) { if (!state) { return CHROMA_ERROR_INIT; @@ -230,11 +262,13 @@ int chroma_wayland_connect(chroma_state_t *state) { state); // Roundtrip to get all globals + chroma_log("TRACE", "Starting Wayland display roundtrip to discover globals"); if (wl_display_roundtrip(state->display) == -1) { chroma_log("ERROR", "Failed to roundtrip Wayland display"); chroma_wayland_disconnect(state); return CHROMA_ERROR_WAYLAND; } + chroma_log("TRACE", "Wayland display roundtrip completed"); // Check if we got a compositor if (!state->compositor) { @@ -301,7 +335,7 @@ void chroma_wayland_disconnect(chroma_state_t *state) { chroma_log("INFO", "Disconnected from Wayland display"); } -/* Output management functions */ +// Output management functions int chroma_output_add(chroma_state_t *state, uint32_t id, struct wl_output *output) { if (!state || !output) { @@ -318,16 +352,19 @@ int chroma_output_add(chroma_state_t *state, uint32_t id, chroma_output->wl_output = output; chroma_output->id = id; - chroma_output->scale = 1; // Default scale + chroma_output->scale = 1; // default scale chroma_output->active = false; chroma_output->state = state; // Add output listener wl_output_add_listener(output, &chroma_output_listener_impl, chroma_output); + chroma_log("TRACE", "Output listener attached for output %u", id); state->output_count++; chroma_log("INFO", "Added output %u (total: %d)", id, state->output_count); + chroma_log("TRACE", + "Output %u initialized with default scale=1, active=false", id); return CHROMA_OK; } @@ -345,25 +382,28 @@ void chroma_output_remove(chroma_state_t *state, uint32_t id) { chroma_log("INFO", "Removing output %u (%s)", id, output->name ? output->name : "unknown"); - /* Clean up surface if it exists */ + // Clean up surface if it exists if (output->surface) { chroma_surface_destroy(output); } - /* Clean up Wayland output */ + // Clean up Wayland output if (output->wl_output) { wl_output_destroy(output->wl_output); } - /* Free allocated strings */ + // Free allocated strings free(output->name); free(output->description); - /* Remove from array by shifting remaining elements */ + // Remove from array by shifting remaining elements int index = output - state->outputs; int remaining = state->output_count - index - 1; + chroma_log("TRACE", "Removing output %u from array: index=%d, remaining=%d", + id, index, remaining); if (remaining > 0) { memmove(output, output + 1, remaining * sizeof(chroma_output_t)); + chroma_log("TRACE", "Shifted %d outputs in array after removal", remaining); } state->output_count--;