diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f2271c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +hellpaper diff --git a/Makefile b/Makefile index abeee07..85ac909 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CC = gcc SRC = hellpaper.c TARGET = hellpaper -CFLAGS = -Wall -O2 +CFLAGS = -Wall -O3 LIBS = -lraylib -lm #-lGL -lpthread -ldl -lrt PREFIX ?= /usr/local diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..686857c --- /dev/null +++ b/flake.lock @@ -0,0 +1,26 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1768200421, + "narHash": "sha256-2wqgHF4f6MoDBOAZCbEGmenPDTiPCVJv2/Np8YZ3C3s=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "aca8e67997d3195aeb603b8808da6f464741c13e", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..836b9c6 --- /dev/null +++ b/flake.nix @@ -0,0 +1,45 @@ +{ + inputs.nixpkgs.url = "github:nixos/nixpkgs"; + + outputs = + { nixpkgs, ... }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + raylibWithJPG = pkgs.raylib.overrideAttrs (finalAttrs: { + cmakeFlags = finalAttrs.cmakeFlags ++ [ "-DSUPPORT_FILEFORMAT_JPG=ON" ]; + }); + in + { + devShells.${system}.default = pkgs.mkShell { + packages = [ + raylibWithJPG + pkgs.pkg-config # For local compilation + linking with raylib + pkgs.bear # For generating compile_commands.json (used by LSPs) + ]; + }; + + packages.${system} = rec { + hellpaper = pkgs.stdenv.mkDerivation { + pname = "hellpaper"; + version = "1.0.0"; + src = ./.; + + nativeBuildInputs = [ raylibWithJPG ]; + + buildPhase = '' + make + ''; + + installPhase = '' + mkdir -p $out/bin + mv ./hellpaper $out/bin/ + ''; + + meta.mainProgram = "hellpaper"; + }; + + default = hellpaper; + }; + }; +} diff --git a/hellpaper.c b/hellpaper.c index 1043336..b492c72 100644 --- a/hellpaper.c +++ b/hellpaper.c @@ -163,6 +163,7 @@ static Particle particles[MAX_POSSIBLE_PARTICLES]; static int wallpaper_count = 0; static bool print_filename_only = false; +static bool recursive_traversal = false; static atomic_int next_load_index = 0; static atomic_bool loader_running = true; @@ -387,9 +388,14 @@ static void LoadWallpapers(const char *dir) struct dirent *entry; while ((entry = readdir(dp)) != NULL && wallpaper_count < g_max_wallpapers) { - if (entry->d_type != DT_REG) + bool is_dot_dir = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0); + if (entry->d_type == DT_DIR && recursive_traversal && !is_dot_dir) { - continue; + char *fullpath; + if (asprintf(&fullpath, "%s/%s", dir, entry->d_name) == -1) continue; + LoadWallpapers(fullpath); + } else if (entry->d_type != DT_REG) { + continue; } const char *ext = strrchr(entry->d_name, '.'); if (!ext || (strcasecmp(ext, ".jpg") != 0 && strcasecmp(ext, ".jpeg") != 0 && strcasecmp(ext, ".png") != 0)) @@ -507,48 +513,54 @@ void ParseConfigFile() void print_help() { - printf("Hellpaper - wallpaper picker for Linux.\n\n"); - printf("USAGE:\n"); - printf(" hellpaper [OPTIONS] [PATH]\n\n"); - printf("ARGUMENTS:\n"); - printf(" [PATH] Optional path to the directory containing wallpapers.\n"); - printf(" Defaults to '~/Pictures/'.\n\n"); - printf("OPTIONS:\n"); - printf(" --help Show this help message and exit.\n"); - printf(" --filename Print only the filename of the selected wallpaper to stdout.\n"); - printf(" --width Set the initial window width.\n"); - printf(" --height Set the initial window height.\n"); - printf(" --startup-effect \n"); - printf(" --keypress-effect \n"); - printf(" --exit-effect \n"); - printf(" Override the configured visual effects on certain events.\n"); - printf(" Available effects: none, glitch, blur, pixelate, shake, collapse, reveal\n\n"); - printf("KEYBINDINGS:\n"); - printf(" NAVIGATION:\n"); - printf(" h, j, k, l / Arrows Move selection. Keys repeat when held.\n"); - printf(" Mouse Wheel Scroll through wallpapers.\n"); - printf(" Ctrl + Mouse Wheel Zoom thumbnail scaling.\n\n"); - printf(" ACTIONS:\n"); - printf(" Enter / LMB Select the highlighted wallpaper and exit.\n"); - printf(" L-Shift / RMB Show a full-screen preview of the highlighted wallpaper.\n"); - printf(" / Enter search mode. Type to filter wallpapers by name.\n"); - printf(" ESC Closes Preview, then Search, then the App.\n\n"); - printf(" VIEW MODES:\n"); - printf(" 1, 2, 3, 4 Switch between different layout modes:\n"); - printf(" 1: Grid\n"); - printf(" 2: Horizontal River\n"); - printf(" 3: Vertical River\n"); - printf(" 4: Wave\n\n"); - printf("CONFIGURATION:\n"); - printf(" Hellpaper can be fully customized by editing the configuration file located at:\n"); - printf(" ~/.config/hellpaper/hellpaper.conf\n"); + printf("Hellpaper - wallpaper picker for Linux.\n\n" + "USAGE:\n" + " hellpaper [OPTIONS] [PATH]\n\n" + "ARGUMENTS:\n" + " [PATH] Optional path to the directory containing wallpapers.\n" + " Defaults to '~/Pictures/'.\n\n" + "OPTIONS:\n" + " --help Show this help message and exit.\n" + " --filename Print only the filename of the selected wallpaper to stdout.\n" + " --recursive Recursively traverse the input directory for wallpapers.\n" + " --width Set the initial window width.\n" + " --height Set the initial window height.\n" + " --startup-effect \n" + " --keypress-effect \n" + " --exit-effect \n" + " Override the configured visual effects on certain events.\n" + " Available effects: none, glitch, blur, pixelate, shake, collapse, reveal\n\n" + "KEYBINDINGS:\n" + " NAVIGATION:\n" + " h, j, k, l / Arrows Move selection. Keys repeat when held.\n" + " q Quit application.\n" + " Mouse Wheel Scroll through wallpapers.\n" + " Ctrl + Mouse Wheel Zoom thumbnail scaling.\n\n" + " ACTIONS:\n" + " Enter / LMB Select the highlighted wallpaper and exit.\n" + " L-Shift / RMB Toggle a full-screen preview of the highlighted wallpaper.\n" + " / Enter search mode. Type to filter wallpapers by name.\n" + " ESC Closes Preview, then Search, then the App.\n\n" + " VIEW MODES:\n" + " 1, 2, 3, 4 Switch between different layout modes:\n" + " 1: Grid\n" + " 2: Horizontal River\n" + " 3: Vertical River\n" + " 4: Wave\n\n" + "CONFIGURATION:\n" + " Hellpaper can be fully customized by editing the configuration file located at:\n" + " ~/.config/hellpaper/hellpaper.conf\n"); } void UpdateAndDrawScene(int filteredCount, int* filteredIndices, float delta, bool isPreviewing, bool isSearching) { int sw = GetScreenWidth(); int sh = GetScreenHeight(); - Vector2 mouse = GetMousePosition(); + + Vector2 mouse_raw = GetMousePosition(); + float scaleX = (float)GetRenderWidth() / (float)GetScreenWidth(); + float scaleY = (float)GetRenderHeight() / (float)GetScreenHeight(); + Vector2 mouse = (Vector2){ mouse_raw.x * scaleX, mouse_raw.y * scaleY }; if (g_modeTransitionTimer > 0) { @@ -743,6 +755,10 @@ int main(int argc, char **argv) { print_filename_only = true; } + else if (strcmp(argv[i], "--recursive") == 0) + { + recursive_traversal = true; + } else if (strcmp(argv[i], "--width") == 0 && i + 1 < argc) { g_win_width = atoi(argv[++i]); @@ -763,7 +779,7 @@ int main(int argc, char **argv) wallpaper_path = default_path; } LoadWallpapers(wallpaper_path); - + SetConfigFlags(FLAG_WINDOW_HIGHDPI); InitWindow(g_win_width, g_win_height, "Hellpaper"); SetExitKey(KEY_NULL); SetTargetFPS(g_max_fps); @@ -794,7 +810,7 @@ int main(int argc, char **argv) TriggerEffect(g_startupEffect, 1.0f); float keyRepeatTimer = 0.0f; - const float KEY_REPEAT_DELAY = 0.1f; + const float KEY_REPEAT_DELAY = 0.15f; while (!WindowShouldClose()) { @@ -881,15 +897,23 @@ int main(int argc, char **argv) if (!blockActions) { int key = GetKeyPressed(); - if (key != 0 && !isSearching) + + // Process exit keycodes first + if ((key == KEY_Q || key == KEY_ESCAPE)) { - TriggerEffect(g_keypressEffect, 0.4f); + break; } + if (key >= KEY_ONE && key < KEY_ONE + NUM_MODES) { g_targetMode = key - KEY_ONE; g_modeTransitionTimer = g_modeTransitionDuration; } + + if (!isSearching) + { + TriggerEffect(g_keypressEffect, 0.4f); + } } bool ateEscKey = false; @@ -909,7 +933,13 @@ int main(int argc, char **argv) } else { - if (!blockActions && IsKeyPressed(KEY_SLASH)) { isSearching = true; searchBufferCount = 0; searchBuffer[0] = '\0'; } + if (!blockActions && IsKeyPressed(KEY_SLASH)) + { + isSearching = true; + g_hoveredIndex = -1; + searchBufferCount = 0; + memset(searchBuffer, 0, 256); + } } @@ -1012,7 +1042,7 @@ int main(int argc, char **argv) } } - if (isPreviewing && (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || IsKeyPressed(KEY_ESCAPE) || IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))) + if (isPreviewing && (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || IsKeyPressed(KEY_ESCAPE) || IsKeyPressed(KEY_LEFT_SHIFT) || IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))) { if(IsKeyPressed(KEY_ESCAPE)) ateEscKey = true; if (atomic_load(&isFullTextureReady)) UnloadTexture(fullPreviewTexture);