Mercurial
view infinite_canvas/theme.c @ 276:b55c22cff335
Add interactive infinite canvas prototype
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 16:57:56 -0700 |
| parents | |
| children | 8d560f50ed4c |
line wrap: on
line source
#include "infinite_canvas/theme.h" #include <stdlib.h> #include <string.h> #if defined(PLATFORM_WEB) || defined(__EMSCRIPTEN__) #include <emscripten/emscripten.h> EM_JS(int, Canvas_Web_Prefers_Dark, (), { return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? 1 : 0; }); #elif defined(_WIN32) #include <windows.h> #else #include <stdio.h> #endif Canvas_Theme_Mode Canvas_Theme_Mode_From_String(const char *p_value) { if (!p_value || strcmp(p_value, "auto") == 0) return CANVAS_THEME_AUTO; if (strcmp(p_value, "light") == 0) return CANVAS_THEME_LIGHT; if (strcmp(p_value, "dark") == 0) return CANVAS_THEME_DARK; return CANVAS_THEME_AUTO; } boolean Canvas_System_Prefers_Dark(void) { #if defined(PLATFORM_WEB) || defined(__EMSCRIPTEN__) return Canvas_Web_Prefers_Dark() ? TRUE : FALSE; #elif defined(_WIN32) DWORD light_theme = 1; DWORD size = sizeof(light_theme); LSTATUS status = RegGetValueA( HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &light_theme, &size); return status == ERROR_SUCCESS && light_theme == 0 ? TRUE : FALSE; #elif defined(__APPLE__) FILE *p_pipe = popen("defaults read -g AppleInterfaceStyle 2>/dev/null", "r"); if (!p_pipe) return FALSE; char value[32] = {0}; boolean dark = fgets(value, sizeof(value), p_pipe) && strstr(value, "Dark") ? TRUE : FALSE; pclose(p_pipe); return dark; #else const char *p_gtk_theme = getenv("GTK_THEME"); if (p_gtk_theme && (strstr(p_gtk_theme, "dark") || strstr(p_gtk_theme, "Dark"))) { return TRUE; } FILE *p_pipe = popen( "gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null", "r"); if (!p_pipe) return FALSE; char value[64] = {0}; boolean dark = fgets(value, sizeof(value), p_pipe) && strstr(value, "prefer-dark") ? TRUE : FALSE; pclose(p_pipe); return dark; #endif } void Canvas_Theme_Resolve(Canvas_Theme *p_theme, Canvas_Theme_Mode mode) { Canvas_Theme_Mode resolved = mode; if (resolved == CANVAS_THEME_AUTO) { resolved = Canvas_System_Prefers_Dark() ? CANVAS_THEME_DARK : CANVAS_THEME_LIGHT; } *p_theme = (Canvas_Theme){ .requested_mode = mode, .resolved_mode = resolved, }; if (resolved == CANVAS_THEME_DARK) { p_theme->background = (Color){15, 15, 17, 255}; p_theme->surface = (Color){24, 24, 27, 255}; p_theme->surface_muted = (Color){39, 39, 42, 255}; p_theme->border = (Color){63, 63, 70, 255}; p_theme->text = (Color){244, 244, 245, 255}; p_theme->text_muted = (Color){161, 161, 170, 255}; p_theme->accent = (Color){96, 165, 250, 255}; p_theme->accent_soft = (Color){30, 58, 95, 255}; p_theme->shadow = (Color){0, 0, 0, 110}; p_theme->toast_surface = (Color){24, 24, 27, 255}; p_theme->toast_border = (Color){63, 63, 70, 255}; } else { p_theme->background = (Color){255, 255, 255, 255}; p_theme->surface = (Color){255, 255, 255, 252}; p_theme->surface_muted = (Color){244, 247, 251, 255}; p_theme->border = (Color){205, 211, 221, 255}; p_theme->text = (Color){24, 24, 27, 255}; p_theme->text_muted = (Color){113, 113, 122, 255}; p_theme->accent = (Color){37, 99, 235, 255}; p_theme->accent_soft = (Color){239, 246, 255, 255}; p_theme->shadow = (Color){15, 23, 42, 36}; p_theme->toast_surface = (Color){255, 255, 255, 255}; p_theme->toast_border = (Color){212, 216, 223, 255}; } } void Canvas_Theme_Toggle(Canvas_Theme *p_theme) { Canvas_Theme_Resolve( p_theme, p_theme->resolved_mode == CANVAS_THEME_DARK ? CANVAS_THEME_LIGHT : CANVAS_THEME_DARK); } void Canvas_Theme_Draw_Shadow( const Canvas_Theme *p_theme, Rectangle bounds, float roundness, int32 segments, float zoom, float opacity) { float offset = 6.0f / zoom; float shadow_alpha = ((float)p_theme->shadow.a / 255.0f) * opacity; DrawRectangleRounded( (Rectangle){ bounds.x + offset, bounds.y + offset, bounds.width, bounds.height, }, roundness, segments, Fade(p_theme->shadow, shadow_alpha)); }