Mercurial > molko
changeset 614:281608524dd1
misc: implement dark/light theming
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 20 Aug 2023 14:45:10 +0200 |
parents | f76cada0bbb2 |
children | ade3030f29f0 |
files | examples/example-label/example-label.c libmlk-core/mlk/core/event.c libmlk-core/mlk/core/event.h libmlk-core/mlk/core/window.c libmlk-core/mlk/core/window.h libmlk-example/mlk/example/example.c libmlk-ui/mlk/ui/ui.c libmlk-ui/mlk/ui/ui.h |
diffstat | 8 files changed, 226 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-label/example-label.c Sun Aug 20 11:14:58 2023 +0200 +++ b/examples/example-label/example-label.c Sun Aug 20 14:45:10 2023 +0200 @@ -17,6 +17,7 @@ */ #include <stddef.h> +#include <stdio.h> #include <mlk/core/core.h> #include <mlk/core/err.h> @@ -44,6 +45,14 @@ .delay = 22 }; +static const char * const theme_names[] = { + [MLK_WINDOW_THEME_AUTO] = "auto", + [MLK_WINDOW_THEME_DARK] = "dark", + [MLK_WINDOW_THEME_LIGHT] = "light" +}; + +static char theme_help_text[128]; + static struct { enum mlk_align align; struct mlk_label label; @@ -51,8 +60,14 @@ { .align = MLK_ALIGN_CENTER, .label = { + .text = theme_help_text + } + }, + { + .align = MLK_ALIGN_CENTER, + .label = { .text = "The world is Malikania.", - .style = &style_glow, + .style = &style_glow } }, { @@ -105,10 +120,6 @@ } }; -static struct mlk_label mouse_label = { - .text = "This one follows your mouse and is not aligned." -}; - static void style_glow_update(struct mlk_label_style *self, struct mlk_label *label, unsigned int ticks) { @@ -119,6 +130,20 @@ } static void +set_help_text(void) +{ + struct mlk_label *l = &table[0].label; + unsigned int w, h; + + snprintf(theme_help_text, sizeof (theme_help_text), "Press space to change theme (%s)", + theme_names[mlk_window.theme_user]); + + mlk_label_query(l, &w, &h); + mlk_align(MLK_ALIGN_CENTER, &l->x, &l->y, w, h, 0, 0, mlk_window.w, mlk_window.h); + l->y += h * 2; +} + +static void init(void) { unsigned int w, h; @@ -127,9 +152,6 @@ if (mlk_example_init("example-label") < 0) mlk_panic(); - /* Change default style for all labels. */ - mlk_label_style->color = 0x005162ff; - /* Change the glowing style. */ style_glow.update = style_glow_update; @@ -139,6 +161,12 @@ mlk_align(table[i].align, &l->x, &l->y, w, h, 0, 0, mlk_window.w, mlk_window.h); } + /* Move a bit the help text. */ + table[0].label.y += 20; + + /* Initialize theme help text. */ + set_help_text(); + mlk_glower_init(&glow); } @@ -146,11 +174,19 @@ handle(struct mlk_state *st, const union mlk_event *ev) { (void)st; + + enum mlk_window_theme theme; + + mlk_ui_handle(ev); switch (ev->type) { - case MLK_EVENT_MOUSE: - mouse_label.x = ev->mouse.x; - mouse_label.y = ev->mouse.y; + case MLK_EVENT_KEYDOWN: + if (ev->key.key == MLK_KEY_SPACE) { + theme = (mlk_window.theme_user + 1) % MLK_WINDOW_THEME_LAST; + mlk_window_set_theme(theme); + mlk_ui_set_theme(mlk_window.theme_effective); + set_help_text(); + } break; case MLK_EVENT_QUIT: mlk_game_quit(); @@ -167,8 +203,6 @@ for (size_t i = 0; i < MLK_UTIL_SIZE(table); ++i) mlk_label_update(&table[i].label, ticks); - - mlk_label_update(&mouse_label, ticks); } static void @@ -176,13 +210,16 @@ { (void)st; - mlk_painter_set_color(MLK_EXAMPLE_BG); + if (mlk_window.theme_effective == MLK_WINDOW_THEME_DARK) + mlk_painter_set_color(0x323558ff); + else + mlk_painter_set_color(0xdcd4ffff); + mlk_painter_clear(); for (size_t i = 0; i < MLK_UTIL_SIZE(table); ++i) mlk_label_draw(&table[i].label); - mlk_label_draw(&mouse_label); mlk_painter_present(); }
--- a/libmlk-core/mlk/core/event.c Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-core/mlk/core/event.c Sun Aug 20 14:45:10 2023 +0200 @@ -287,6 +287,23 @@ } } +static void +convert_theme(union mlk_event *ev) +{ + ev->type = MLK_EVENT_THEME; + + switch (SDL_GetSystemTheme()) { + case SDL_SYSTEM_THEME_DARK: + ev->theme.theme = MLK_WINDOW_THEME_DARK; + break; + default: + ev->theme.theme = MLK_WINDOW_THEME_LIGHT; + break; + } + + mlk_window.theme_effective = ev->theme.theme; +} + int mlk_event_poll(union mlk_event *ev) { @@ -321,8 +338,18 @@ case SDL_EVENT_GAMEPAD_AXIS_MOTION: convert_axis(&event, ev); return 1; + case SDL_EVENT_SYSTEM_THEME_CHANGED: + /* + * We only report the event if the user preferrence is + * set to auto because we don't need it otherwise. + */ + if (mlk_window.theme_user == MLK_WINDOW_THEME_AUTO) { + convert_theme(ev); + return 1; + } + break; default: - continue; + break; } }
--- a/libmlk-core/mlk/core/event.h Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-core/mlk/core/event.h Sun Aug 20 14:45:10 2023 +0200 @@ -37,6 +37,7 @@ #include "key.h" #include "mouse.h" #include "gamepad.h" +#include "window.h" /** * \enum mlk_event_type @@ -100,6 +101,11 @@ MLK_EVENT_AXIS, /** + * Operating system theme changed. + */ + MLK_EVENT_THEME, + + /** * Window manager quit event. * * No value. @@ -218,6 +224,23 @@ }; /** + * \struct mlk_event_theme + * \brief Operating system theme changed + */ +struct mlk_event_theme { + /** + * Set to ::MLK_EVENT_THEME. + */ + enum mlk_event_type type; + + /** + * New effective theme ::MLK_WINDOW_THEME_DARK or + * ::MLK_WINDOW_THEME_LIGHT. + */ + enum mlk_window_theme theme; +}; + +/** * \union mlk_event * \brief Generic input event */ @@ -251,6 +274,11 @@ * For ::MLK_EVENT_AXIS. */ struct mlk_event_axis axis; + + /** + * For ::MLK_EVENT_THEME. + */ + struct mlk_event_theme theme; }; #if defined(__cplusplus)
--- a/libmlk-core/mlk/core/window.c Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-core/mlk/core/window.c Sun Aug 20 14:45:10 2023 +0200 @@ -34,7 +34,9 @@ static SDL_Cursor *cursors[MLK_WINDOW_CURSOR_LAST]; struct mlk_window mlk_window = { - .handle = &handle + .handle = &handle, + .theme_user = MLK_WINDOW_THEME_AUTO, + .theme_effective = MLK_WINDOW_THEME_LIGHT, }; static void @@ -75,7 +77,7 @@ static int load_renderer(void) { - return (handle.renderer = SDL_CreateRenderer(handle.win, NULL, 0)); + return (handle.renderer = SDL_CreateRenderer(handle.win, NULL, 0)) != NULL; } int @@ -94,6 +96,8 @@ load_framerate(); load_cursors(); + mlk_window_set_theme(mlk_window.theme_user); + return 0; } @@ -111,6 +115,22 @@ } void +mlk_window_set_theme(enum mlk_window_theme theme) +{ + assert(theme >= 0 && theme < MLK_WINDOW_THEME_LAST); + + mlk_window.theme_user = theme; + + if (theme == MLK_WINDOW_THEME_AUTO) { + if (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) + mlk_window.theme_effective = MLK_WINDOW_THEME_DARK; + else + mlk_window.theme_effective = MLK_WINDOW_THEME_LIGHT; + } else + mlk_window.theme_effective = mlk_window.theme_user; +} + +void mlk_window_finish(void) { if (handle.renderer)
--- a/libmlk-core/mlk/core/window.h Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-core/mlk/core/window.h Sun Aug 20 14:45:10 2023 +0200 @@ -30,6 +30,37 @@ */ /** + * \enum mlk_window_theme + * \brief Operating system theme. + * + * This enumeration is used for both user preference and current effective theme + * which are two distinct things. If user selects `auto` then the effective + * theme will be set either to light or dark depending on the system platform. + */ +enum mlk_window_theme { + /** + * Prefer the operating system user preference, if theme can't be + * detected it will be set to light instead. + */ + MLK_WINDOW_THEME_AUTO, + + /** + * Light theme. + */ + MLK_WINDOW_THEME_LIGHT, + + /** + * Dark theme. + */ + MLK_WINDOW_THEME_DARK, + + /** + * Unused sentinel value. + */ + MLK_WINDOW_THEME_LAST +}; + +/** * \struct mlk_window * \brief Window structure */ @@ -55,6 +86,27 @@ */ unsigned int framerate; + /** + * (read-only) + * + * User preferred theme. + * + * \warning Do not set this variable manually, it won't have any effect + * use ::mlk_window_set_theme instead. + */ + enum mlk_window_theme theme_user; + + /** + * (read-only) + * + * Current effective theme depending on the user preferred setting, this + * value holds either ::MLK_WINDOW_THEME_LIGHT or + * ::MLK_WINDOW_THEME_DARK only. + * + * \warning Do not set this variable manually, it won't have any effect. + */ + enum mlk_window_theme theme_effective; + /** \cond MLK_PRIVATE_DECLS */ void *handle; /** \endcond MLK_PRIVATE_DECLS */ @@ -144,6 +196,17 @@ mlk_window_set_cursor(enum mlk_window_cursor cursor); /** + * Select a preferred user theme for the window (auto, dark or light). + * + * This function will adjust ::mlk_window::theme_user and + * ::mlk_window::theme_effective. + * + * \param theme the new user theme + */ +void +mlk_window_set_theme(enum mlk_window_theme theme); + +/** * Destroy the window. */ void
--- a/libmlk-example/mlk/example/example.c Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-example/mlk/example/example.c Sun Aug 20 14:45:10 2023 +0200 @@ -45,6 +45,7 @@ if (mlk_window_open(name, MLK_EXAMPLE_W, MLK_EXAMPLE_H) < 0) return err; + mlk_ui_set_theme(mlk_window.theme_effective); mlk_registry_init(); return 0;
--- a/libmlk-ui/mlk/ui/ui.c Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-ui/mlk/ui/ui.c Sun Aug 20 14:45:10 2023 +0200 @@ -24,7 +24,10 @@ #include <libintl.h> +#include <SDL.h> + #include <mlk/core/err.h> +#include <mlk/core/event.h> #include <mlk/core/font.h> #include <mlk/core/texture.h> #include <mlk/core/trace.h> @@ -34,6 +37,7 @@ #include <assets/fonts/opensans-regular.h> #include "align.h" +#include "label.h" #include "ui.h" #include "ui_p.h" @@ -55,7 +59,8 @@ FONT_DEF(assets_fonts_opensans_regular, 14, MLK_UI_FONT_INTERFACE) }; -struct mlk_font mlk_ui_fonts[MLK_UI_FONT_LAST] = {0}; +/* Global fonts. */ +struct mlk_font mlk_ui_fonts[MLK_UI_FONT_LAST] = {}; int mlk_ui_init(void) @@ -80,6 +85,23 @@ } void +mlk_ui_handle(const union mlk_event *ev) +{ + if (ev->type == MLK_EVENT_THEME) + mlk_ui_set_theme(ev->theme.theme); +} + +void +mlk_ui_set_theme(enum mlk_window_theme theme) +{ + if (theme == MLK_WINDOW_THEME_DARK) { + mlk_label_style = &mlk_label_style_dark; + } else { + mlk_label_style = &mlk_label_style_light; + } +} + +void mlk_ui_draw_text(enum mlk_align align, struct mlk_font *font, unsigned long color,
--- a/libmlk-ui/mlk/ui/ui.h Sun Aug 20 11:14:58 2023 +0200 +++ b/libmlk-ui/mlk/ui/ui.h Sun Aug 20 14:45:10 2023 +0200 @@ -34,6 +34,9 @@ #define MLK_UI_BORDER (2) enum mlk_align; +enum mlk_window_theme; + +union mlk_event; enum mlk_ui_font { MLK_UI_FONT_INTERFACE, @@ -49,6 +52,12 @@ int mlk_ui_init(void); +void +mlk_ui_handle(const union mlk_event *ev); + +void +mlk_ui_set_theme(enum mlk_window_theme theme); + /* TODO: probably better somewhere else? */ void mlk_ui_draw_text(enum mlk_align align,