aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-05-28 21:00:11 -0400
committeriamcheeseman <[email protected]>2026-05-28 21:00:11 -0400
commit3d80fc2bcc2888ae5ce2d1334eb9ec30fac544ea (patch)
treec968f1b32f884b550cc7fb54f906d94a995f1680
parent78520499d6c444e435879eef1ac96cdff9e6c4d1 (diff)
window scrolling
-rw-r--r--platform/desktop/desktop.c18
-rw-r--r--teensy/teensy_platform.h1
-rw-r--r--teensy/teensy_ui.c58
-rw-r--r--teensy/teensy_ui.h2
4 files changed, 57 insertions, 22 deletions
diff --git a/platform/desktop/desktop.c b/platform/desktop/desktop.c
index 9574c9c..b156e56 100644
--- a/platform/desktop/desktop.c
+++ b/platform/desktop/desktop.c
@@ -45,6 +45,7 @@ typedef struct {
GLint uniform_tex_loc;
GLuint screen_handle;
uint32_t typed;
+ double scroll;
} Desktop_Platform;
Desktop_Platform p;
@@ -57,6 +58,15 @@ void character_callback(GLFWwindow *window, unsigned int cp)
}
static
+void scroll_callback(GLFWwindow* window, double x, double y)
+{
+ (void)window;
+ (void)x;
+ p.scroll = y;
+}
+
+
+static
GLuint compile_shader(GLenum type, const char *src)
{
GLuint shader = glCreateShader(type);
@@ -102,6 +112,7 @@ void ty_platform_init(ty_Ctx *ctx)
ty_log_fatal(TY_PLATFORM_ERR, "could not load GLAD");
glfwSetCharCallback(p.win, character_callback);
+ glfwSetScrollCallback(p.win, scroll_callback);
ty_Vec2 vertices[] = {
ty_vec2(-1, -1), ty_vec2(0, 1),
@@ -180,6 +191,8 @@ void ty_platform_deinit(void)
void ty_platform_frame(ty_Image img)
{
+ p.scroll = 0;
+
glfwPollEvents();
int win_width, win_height;
@@ -283,3 +296,8 @@ bool ty_platform_get_typed_char(uint32_t *c)
p.typed = 0;
return true;
}
+
+int ty_platform_get_scroll(void)
+{
+ return (int)p.scroll;
+}
diff --git a/teensy/teensy_platform.h b/teensy/teensy_platform.h
index 8a1daa6..419922c 100644
--- a/teensy/teensy_platform.h
+++ b/teensy/teensy_platform.h
@@ -16,5 +16,6 @@ bool ty_platform_is_button_down(ty_Button btn);
// Optional, no editor if not implemented
ty_Vec2i ty_platform_get_mouse(void);
bool ty_platform_get_typed_char(uint32_t *c);
+int ty_platform_get_scroll(void);
#endif // TEENSY_PLATFORM_H_
diff --git a/teensy/teensy_ui.c b/teensy/teensy_ui.c
index 4dd9d5d..5913005 100644
--- a/teensy/teensy_ui.c
+++ b/teensy/teensy_ui.c
@@ -56,11 +56,11 @@ typedef struct {
Layout layout_stack[MAX_LAYOUTS];
ty_Recti rect;
uint32_t flags;
- bool focused;
bool lmb_down;
bool rmb_down;
bool lmb_pressed;
bool rmb_pressed;
+ int scroll;
} Window;
typedef struct {
@@ -77,6 +77,7 @@ typedef struct {
ty_Vec2i prev_mouse_pos;
+ Window *focused_win;
const tyui_Text_Input *focused_text_box;
} Ctx;
@@ -84,6 +85,18 @@ static tyui_Style default_style;
static Ctx tyui;
static
+ty_Recti win_content(Window *win)
+{
+ ty_Recti rect = win->rect;
+ if (!(win->flags & TYUI_WIN_NOTITLE)) {
+ rect.y += tyui.style.title_bar_height;
+ rect.h -= tyui.style.title_bar_height;
+ }
+
+ return rect;
+}
+
+static
void rect_cmd(ty_Recti rect, ty_Color color)
{
Cmd cmd = {0};
@@ -123,9 +136,9 @@ void clip_cmd(ty_Recti rect)
cmd.kind = CMD_CLIP;
if (rect.w < 0 || rect.h < 0)
- rect = window()->rect; // This is a full screen clip
+ rect = win_content(window()); // This is a full screen clip
- cmd.rect = ty_recti_clamp(rect, window()->rect);
+ cmd.rect = ty_recti_clamp(rect, win_content(window()));
ty_list_append(&window()->cmds, cmd);
}
@@ -214,18 +227,6 @@ bool is_hovered(ty_Recti rect)
}
static
-ty_Recti win_rect(Window *win)
-{
- ty_Recti rect = win->rect;
- if (!(win->flags & TYUI_WIN_NOTITLE)) {
- rect.y += tyui.style.title_bar_height;
- rect.h -= tyui.style.title_bar_height;
- }
-
- return rect;
-}
-
-static
Window create_window(ty_Recti rect, uint32_t flags)
{
Window win = {0};
@@ -263,7 +264,9 @@ void tyui_init(const ty_Font *font)
root_flags |= TYUI_WIN_NORESIZEY;
root_flags |= TYUI_WIN_NOCLOSE;
root_flags |= TYUI_WIN_NOMOVE;
+ root_flags |= TYUI_WIN_NOTITLE;
root_flags |= TYUI_WIN_INVISIBLE;
+ root_flags |= TYUI_WIN_ALWAYS_BELOW;
tyui.root = create_window(
ty_recti(0, 0, ctx.hints.scr_width, ctx.hints.scr_height),
@@ -325,6 +328,8 @@ bool tyui_begin_window_ex(tyui_Window_Conf conf, bool *closed_ptr)
assert(conf.title);
assert(conf.id);
+ tyui.active = &tyui.root;
+
bool closed = false;
if (closed_ptr)
@@ -345,7 +350,6 @@ bool tyui_begin_window_ex(tyui_Window_Conf conf, bool *closed_ptr)
}
Window *win = &tyui.windows[*conf.id - 1];
- tyui.active = win;
win->layout = win->layout_stack;
ty_Vec2i mouse_pos = ty_mouse_pos();
@@ -415,7 +419,7 @@ bool tyui_begin_window_ex(tyui_Window_Conf conf, bool *closed_ptr)
if (win->flags & TYUI_WIN_INVISIBLE)
goto skip_invisible;
- ty_Recti body_rect = win_rect(win);
+ ty_Recti body_rect = win_content(win);
rect_cmd(body_rect, tyui.style.win_border);
rect_cmd(ty_recti_shrink(body_rect, 1), tyui.style.win_bg);
@@ -437,8 +441,19 @@ bool tyui_begin_window_ex(tyui_Window_Conf conf, bool *closed_ptr)
skip_invisible:
+ tyui.active = win;
+ clip_cmd(win_content(win));
+
+ // TODO: Maybe make a distinction between focused and the top-most hovered
+ // window? By forcing the user to focus the window, they must click on it
+ // beforehand, which is bad UX.
+ if (tyui.focused_win == win && is_hovered(win->rect)) {
+ win->scroll += ty_platform_get_scroll() * TYUI_SCROLL;
+ win->scroll = ty_min(win->scroll, 0);
+ }
+
tyui_push_layout((float[]){-1, 0});
- layout()->total_height = tyui.style.padding;
+ layout()->total_height = tyui.style.padding + win->scroll;
if ((win->flags & TYUI_WIN_NOTITLE) == 0)
layout()->total_height += tyui.style.title_bar_height;
@@ -452,9 +467,9 @@ void tyui_end_window(void)
return;
}
- clip_cmd(TY_CLIP_NONE);
-
tyui.active = &tyui.root;
+
+ clip_cmd(window()->rect);
}
void tyui_text_ex(tyui_Align align, const char *fmt, ...)
@@ -647,7 +662,7 @@ void focus_window(tyui_Id win_id)
ty_log_err("uh oh");
Window *win = &tyui.windows[win_id - 1];
- win->focused = true;
+ tyui.focused_win = win;
if (win->flags & TYUI_WIN_ALWAYS_BELOW)
return;
@@ -665,7 +680,6 @@ void update_windows(void)
win->rmb_down = false;
win->lmb_pressed = false;
win->rmb_pressed = false;
- win->focused = false;
}
for (int i = tyui.window_count - 1; i >= 0; i--) {
diff --git a/teensy/teensy_ui.h b/teensy/teensy_ui.h
index c1081d4..237d140 100644
--- a/teensy/teensy_ui.h
+++ b/teensy/teensy_ui.h
@@ -15,6 +15,8 @@
#define TYUI_WIN_INVISIBLE (1 << 5)
#define TYUI_WIN_ALWAYS_BELOW (1 << 6)
+#define TYUI_SCROLL (7)
+
// Marks the beginning of a window, with sane defaults.
#define tyui_begin_window(_title, _rect, _id, ...) \
tyui_begin_window_ex((tyui_Window_Conf){ \