Mercurial > molko
changeset 163:4bbfcd9180a8
core: add window_set_cursor function, closes #2502
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 18 Oct 2020 17:14:42 +0200 |
parents | 629f55f3961e |
children | 87f8ef73a160 |
files | examples/CMakeLists.txt examples/example-cursor.c examples/example-ui.c libcore/core/window.c libcore/core/window.h |
diffstat | 5 files changed, 209 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/CMakeLists.txt Sun Oct 18 12:01:59 2020 +0200 +++ b/examples/CMakeLists.txt Sun Oct 18 17:14:42 2020 +0200 @@ -29,6 +29,13 @@ ) molko_define_executable( + TARGET example-cursor + SOURCES example-cursor.c + FOLDER examples + LIBRARIES libui +) + +molko_define_executable( TARGET example-debug SOURCES example-debug.c FOLDER examples
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-cursor.c Sun Oct 18 17:14:42 2020 +0200 @@ -0,0 +1,140 @@ +/* + * example-cursor.c -- example on how to change cursor + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> + +#include <core/clock.h> +#include <core/core.h> +#include <core/event.h> +#include <core/key.h> +#include <core/painter.h> +#include <core/panic.h> +#include <core/sys.h> +#include <core/util.h> +#include <core/window.h> + +#include <ui/label.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 + +static char help_text[128]; + +static struct label help = { + .x = 10, + .y = 10, + .text = help_text, + .flags = LABEL_FLAGS_SHADOW +}; + +static void +init(void) +{ + if (!core_init() || !ui_init()) + panic(); + if (!window_open("Example - Cursor", W, H)) + panic(); +} + +static void +change(enum window_cursor cursor) +{ + static const char *names[] = { + [WINDOW_CURSOR_ARROW] = "WINDOW_CURSOR_ARROW", + [WINDOW_CURSOR_EDIT] = "WINDOW_CURSOR_EDIT", + [WINDOW_CURSOR_WAIT] = "WINDOW_CURSOR_WAIT", + [WINDOW_CURSOR_CROSSHAIR] = "WINDOW_CURSOR_CROSSHAIR", + [WINDOW_CURSOR_SIZE] = "WINDOW_CURSOR_SIZE", + [WINDOW_CURSOR_NO] = "WINDOW_CURSOR_NO", + [WINDOW_CURSOR_HAND] = "WINDOW_CURSOR_HAND" + }; + + snprintf(help_text, sizeof (help_text), "Keys: <Left>/<Right> to change cursor. Current: %s", names[cursor]); + window_set_cursor(cursor); +} + +static void +run(void) +{ + struct clock clock = {0}; + enum window_cursor cursor = WINDOW_CURSOR_ARROW; + + clock_start(&clock); + change(cursor); + + for (;;) { + union event ev; + unsigned int elapsed = clock_elapsed(&clock); + + clock_start(&clock); + + while (event_poll(&ev)) { + switch (ev.type) { + case EVENT_KEYDOWN: + switch (ev.key.key) { + case KEY_LEFT: + if (cursor > 0) + change(--cursor); + break; + case KEY_RIGHT: + if (cursor + 1 < WINDOW_CURSOR_LAST) + change(++cursor); + break; + default: + break; + } + + + break; + case EVENT_QUIT: + return; + default: + break; + } + } + + painter_set_color(0xebede9ff); + painter_clear(); + label_draw(&help); + painter_present(); + + if ((elapsed = clock_elapsed(&clock)) < 20) + delay(20 - elapsed); + } +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +} +
--- a/examples/example-ui.c Sun Oct 18 12:01:59 2020 +0200 +++ b/examples/example-ui.c Sun Oct 18 17:14:42 2020 +0200 @@ -258,12 +258,14 @@ ui.motion.active = true; ui.motion.x = ev.click.x; ui.motion.y = ev.click.y; + window_set_cursor(WINDOW_CURSOR_SIZE); } else action_stack_handle(&ui.st, &ev); break; case EVENT_CLICKUP: ui.motion.active = false; + window_set_cursor(WINDOW_CURSOR_ARROW); /* Fallthrough. */ default: action_stack_handle(&ui.st, &ev);
--- a/libcore/core/window.c Sun Oct 18 12:01:59 2020 +0200 +++ b/libcore/core/window.c Sun Oct 18 17:14:42 2020 +0200 @@ -22,6 +22,7 @@ #include <SDL.h> #include "error_p.h" +#include "util.h" #include "window.h" #include "window_p.h" @@ -30,10 +31,32 @@ .renderer = NULL }; +static SDL_Cursor *cursors[WINDOW_CURSOR_LAST]; + struct window window = { .handle = &handle }; +static void +load_cursors(void) +{ + cursors[WINDOW_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + cursors[WINDOW_CURSOR_EDIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + cursors[WINDOW_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); + cursors[WINDOW_CURSOR_CROSSHAIR] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR); + cursors[WINDOW_CURSOR_SIZE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + cursors[WINDOW_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); + cursors[WINDOW_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); +} + +static void +finish_cursors(void) +{ + for (size_t i = 0; i < NELEM(cursors); ++i) + if (cursors[i]) + SDL_FreeCursor(cursors[i]); +} + bool window_open(const char *title, unsigned int w, unsigned int h) { @@ -48,10 +71,20 @@ window.w = w; window.h = h; + load_cursors(); + return true; } void +window_set_cursor(enum window_cursor cursor) +{ + assert(cursor < WINDOW_CURSOR_LAST); + + SDL_SetCursor(cursors[cursor]); +} + +void window_finish(void) { if (handle.renderer) @@ -59,5 +92,7 @@ if (handle.win) SDL_DestroyWindow(handle.win); + finish_cursors(); + memset(&handle, 0, sizeof (handle)); }
--- a/libcore/core/window.h Sun Oct 18 12:01:59 2020 +0200 +++ b/libcore/core/window.h Sun Oct 18 17:14:42 2020 +0200 @@ -37,6 +37,20 @@ }; /** + * \brief Window mouse cursor. + */ +enum window_cursor { + WINDOW_CURSOR_ARROW, + WINDOW_CURSOR_EDIT, + WINDOW_CURSOR_WAIT, + WINDOW_CURSOR_CROSSHAIR, + WINDOW_CURSOR_SIZE, + WINDOW_CURSOR_NO, + WINDOW_CURSOR_HAND, + WINDOW_CURSOR_LAST +}; + +/** * \brief Access to global window structure. */ extern struct window window; @@ -54,6 +68,17 @@ window_open(const char *title, unsigned int width, unsigned int height); /** + * Change the window cursor. + * + * You must open a window before calling this function. + * + * \pre cursor < WINDOW_CURSOR_LAST + * \param cursor the cursor + */ +void +window_set_cursor(enum window_cursor cursor); + +/** * Close the window and destroy associated resources. */ void