diff options
Diffstat (limited to 'lib/liboda')
-rw-r--r-- | lib/liboda/include/liboda/input.h | 74 | ||||
-rw-r--r-- | lib/liboda/include/liboda/oda.h | 23 | ||||
-rw-r--r-- | lib/liboda/include/liboda/types.h | 1 | ||||
-rw-r--r-- | lib/liboda/src/input.c | 88 | ||||
-rw-r--r-- | lib/liboda/src/window.c | 206 |
5 files changed, 388 insertions, 4 deletions
diff --git a/lib/liboda/include/liboda/input.h b/lib/liboda/include/liboda/input.h new file mode 100644 index 0000000..c74a304 --- /dev/null +++ b/lib/liboda/include/liboda/input.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBODA_INPUT_H +#define LIBODA_INPUT_H + +#include <stdint.h> +#include <stddef.h> + +/* + * Macros to help extract scancode and + * character + */ +#define ODA_SCANCODE(KEY) ((KEY) >> 8) +#define ODA_KEYCHAR(KEY) ((char )(KEY) & 0xFF) + +/* + * Key defines + */ +#define ODA_KEY_OTHER 0x0000 +#define ODA_KEY_ESCAPE 0x0001 +#define ODA_KEY_TAB 0x0002 +#define ODA_KEY_BACKSPACE 0x0003 + +/* + * Represents a key press + * + * @type: Key types (see ODA_KEY_*) + * @scancode: Scancode + * @ch: Character + */ +struct oda_key { + uint16_t type; + uint8_t scancode; + char ch; +}; + +/* + * ODA keyboard object for managing keyboard + * input. + */ +struct oda_kbd { + int(*handle_keyev)(struct oda_kbd *kbd, struct oda_key *key); +}; + +int oda_kbd_dispatch(struct oda_kbd *kbd); + +#endif /* !LIBODA_INPUT_H */ diff --git a/lib/liboda/include/liboda/oda.h b/lib/liboda/include/liboda/oda.h index 10738a9..9d96f2f 100644 --- a/lib/liboda/include/liboda/oda.h +++ b/lib/liboda/include/liboda/oda.h @@ -40,10 +40,12 @@ /* * ODA representation of a window. * + * @wid: Window ID (identifies the window) * @surface: Window surface descriptor * @session: Session this window belongs to */ struct oda_window { + odawid_t wid; struct gfx_shape surface; struct oda_state *session; TAILQ_ENTRY(oda_window) link; @@ -81,6 +83,22 @@ struct oda_wattr { }; /* + * Arguments for oda_movewin() are stored + * within this structure to minimize the + * number of arguments within the function + * signature. + * + * @wp: Window to be moved + * @to_x: X position to move window to + * @to_y: Y position to move window to + */ +struct oda_movewin { + struct oda_window *wp; + odapos_t to_x; + odapos_t to_y; +}; + +/* * A pixel point that can be plotted * onto a window. * @@ -99,9 +117,12 @@ struct oda_point { int oda_reqwin(struct oda_wattr *params, struct oda_window **res); int oda_termwin(struct oda_state *state, struct oda_window *win); -int oda_plotwin(struct oda_state *state, const struct oda_point *point); +int oda_plotwin(struct oda_state *state, const struct oda_point *point); +int oda_movewin(struct oda_state *state, struct oda_movewin *params); int oda_start_win(struct oda_state *state, struct oda_window *win); + int oda_init(struct oda_state *res); +int oda_shutdown(struct oda_state *state); #endif /* !LIBODA_ODA_H */ diff --git a/lib/liboda/include/liboda/types.h b/lib/liboda/include/liboda/types.h index 8b77aa7..ec12330 100644 --- a/lib/liboda/include/liboda/types.h +++ b/lib/liboda/include/liboda/types.h @@ -36,5 +36,6 @@ typedef uint32_t odapos_t; /* X/Y positions */ typedef uint32_t odapix_t; /* RGB pixel */ typedef odapix_t odacolor_t; /* RGB color */ typedef uint32_t odadimm_t; /* Dimensions */ +typedef uint32_t odawid_t; /* Window ID */ #endif /* !LIBODA_TYPE_H */ diff --git a/lib/liboda/src/input.c b/lib/liboda/src/input.c new file mode 100644 index 0000000..797a9d4 --- /dev/null +++ b/lib/liboda/src/input.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/ascii.h> +#include <sys/errno.h> +#include <sys/param.h> +#include <liboda/oda.h> +#include <liboda/input.h> +#include <stdint.h> +#include <stdio.h> + +/* + * Convert key scancode/char values to fixed + * ODA key constants + */ +static inline uint16_t +oda_map_key(const struct oda_key *key) +{ + uint16_t type = ODA_KEY_OTHER; + + switch (key->ch) { + case ASCII_ESC: + type = ODA_KEY_ESCAPE; + break; + case ASCII_HT: + type = ODA_KEY_TAB; + break; + case ASCII_BS: + type = ODA_KEY_BACKSPACE; + break; + } + + return type; +} + +/* + * Dispatch keyboard events. This is typically + * called in an event loop so that keyboard events + * are handled per iteration. + * + * @kbd: Keyboard to monitor + */ +int +oda_kbd_dispatch(struct oda_kbd *kbd) +{ + struct oda_key key; + int input; + + if (kbd == NULL) { + return -EINVAL; + } + + /* Attempt to grab the input */ + if ((input = getchar()) < 0) { + return -EAGAIN; + } + + key.scancode = ODA_SCANCODE(input); + key.ch = ODA_KEYCHAR(input); + key.type = oda_map_key(&key); + return kbd->handle_keyev(kbd, &key); +} diff --git a/lib/liboda/src/window.c b/lib/liboda/src/window.c index 9a8b799..216b106 100644 --- a/lib/liboda/src/window.c +++ b/lib/liboda/src/window.c @@ -28,12 +28,121 @@ */ #include <sys/errno.h> +#include <sys/queue.h> #include <stdlib.h> #include <string.h> #include <liboda/oda.h> #include <liboda/odavar.h> #include <liboda/types.h> #include <libgfx/gfx.h> +#include <libgfx/draw.h> + +/* + * The window cache is used to reduce how many + * calls to malloc() and free() are made during + * window creation and destruction. + */ +static TAILQ_HEAD(, oda_window) wcache; +static uint32_t wcache_cookie = 0; +static odawid_t next_wid = 1; + +/* + * Pop a window from the window cache. + * Returns NULL there are no more windows. + */ +static struct oda_window * +oda_window_pop(void) +{ + struct oda_window *wdp; + + if (wcache_cookie != ODA_COOKIE) { + TAILQ_INIT(&wcache); + wcache_cookie = ODA_COOKIE; + return NULL; + } + + wdp = TAILQ_FIRST(&wcache); + TAILQ_REMOVE(&wcache, wdp, link); + return wdp; +} + +/* + * Place a window into the window cache. + */ +static void +oda_window_cache(struct oda_window *wdp) +{ + /* Ensure arg is valid */ + if (wdp == NULL) { + return; + } + + if (wcache_cookie != ODA_COOKIE) { + TAILQ_INIT(&wcache); + wcache_cookie = ODA_COOKIE; + } + + TAILQ_INSERT_TAIL(&wcache, wdp, link); +} + +/* + * Allocate an ODP window + * + * Returns NULL on failure + */ +static struct oda_window * +oda_window_alloc(void) +{ + struct oda_window *wdp; + + /* + * First check if there are any entries + * we can grab from the window cache. + */ + wdp = oda_window_pop(); + if (wdp != NULL) { + return wdp; + } + + /* Allocate a new window */ + wdp = malloc(sizeof(*wdp)); + if (wdp == NULL) { + return NULL; + } + + memset(wdp, 0, sizeof(*wdp)); + wdp->wid = next_wid++; + return wdp; +} + +/* + * Release a given ODA window descriptor + * + * @wdp: Window to free + */ +static void +oda_window_release(struct oda_state *state, struct oda_window *wdp) +{ + if (wdp == NULL) { + return; + } + + /* + * It is probably a good idea to ensure previous + * state other than the old window ID is reset + * and zeroed. + */ + wdp->session = NULL; + memset(&wdp->surface, 0, sizeof(wdp->surface)); + + /* + * Now we can remove this window from the list + * of windows we are tracking and add it to the + * cache. + */ + TAILQ_REMOVE(&state->winq, wdp, link); + oda_window_cache(wdp); +} /* * Check if a point is within the bounds of @@ -78,6 +187,34 @@ oda_check_point(struct oda_window *wp, struct oda_point *point) } /* + * Clean up after ourselves and release + * each entry of the wcache. + * + * Returns 0 on success. + */ +static int +oda_free_wcache(void) +{ + struct oda_window *wdp, *next; + + if (wcache_cookie != ODA_COOKIE) { + return -1; + } + + /* + * Go through each entry and call free() + * on them. + */ + wdp = TAILQ_FIRST(&wcache); + while (wdp != NULL) { + next = TAILQ_NEXT(wdp, link); + free(wdp); + wdp = next; + } + return 0; +} + +/* * Plot a pixel onto a window * * @state: ODA state pointer @@ -176,7 +313,7 @@ oda_reqwin(struct oda_wattr *params, struct oda_window **res) } /* Allocate a new window */ - wp = malloc(sizeof(*wp)); + wp = oda_window_alloc(); if (wp == NULL) { return -ENOMEM; } @@ -205,6 +342,61 @@ oda_reqwin(struct oda_wattr *params, struct oda_window **res) } /* + * Move a window to a new position on the + * screen. + * + * @state: ODA state pointer + * @params: Arguments to this function + */ +int +oda_movewin(struct oda_state *state, struct oda_movewin *params) +{ + struct oda_window *win; + struct gfx_shape *wsurf; + struct gfx_region r; + odadimm_t w, h; + odapos_t x, y, x_f, y_f; + odapos_t to_x, to_y; + uint32_t i = 0; + int error; + + /* Make sure arguments are valid */ + if (state == NULL || params == NULL) { + return -EINVAL; + } + + /* We need the window */ + if ((win = params->wp) == NULL) { + return -EINVAL; + } + + /* Verify state cookie */ + if ((error = oda_cookie_verify(state)) != 0) { + return error; + } + + wsurf = &win->surface; + to_x = params->to_x; + to_y = params->to_y; + + r.x = wsurf->x; + r.y = wsurf->y; + r.width = wsurf->width; + r.height = wsurf->height; + + /* + * We will copy the window to the new location and + * fill where the old window was with GFX_BLACK. + * + * TODO: Handle overlapping of windows + */ + gfx_copy_region(&state->gctx, &r, to_x, to_y); + wsurf->x = to_x; + wsurf->y = to_y; + return 0; +} + +/* * Register a window into the current ODA state. * Everytime a compositor requests a window, we * must keep track of it. @@ -255,7 +447,15 @@ oda_termwin(struct oda_state *state, struct oda_window *win) return error; } - TAILQ_REMOVE(&state->winq, win, link); - free(win); + oda_window_release(state, win); return 0; } + +/* + * Shutdown the ODA library + */ +int +oda_shutdown(struct oda_state *state) +{ + return oda_free_wcache(); +} |