aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-05-01 21:38:49 +1200
committerArslaan Pathan <[email protected]>2026-05-01 21:38:49 +1200
commit6ad244502d1c3c09a26012c5e7fad901c95cc38e (patch)
treeb0b8106fca78a49e47313f35d8245eeb6980d3ac
parentccb8f9316c9bc7aded2dd5d74d2e82445bf2f647 (diff)
downloadsaffron-6ad244502d1c3c09a26012c5e7fad901c95cc38e.tar.xz
saffron-6ad244502d1c3c09a26012c5e7fad901c95cc38e.zip
Fix the buttons and implement hooks for future webkit bindings to build on top of
-rw-r--r--include/saffron_api.h6
-rw-r--r--include/saffron_event_hooks.h13
-rw-r--r--include/saffron_window.h3
-rw-r--r--meson.build4
-rw-r--r--src/saffron_button.c37
-rw-r--r--src/saffron_event_hooks.c19
-rw-r--r--src/saffron_window.c6
-rw-r--r--tests/test_hooks.c36
-rw-r--r--tests/test_main.c9
9 files changed, 123 insertions, 10 deletions
diff --git a/include/saffron_api.h b/include/saffron_api.h
index 8ad340c..964eaa9 100644
--- a/include/saffron_api.h
+++ b/include/saffron_api.h
@@ -36,4 +36,10 @@ SaffronButton* saffron_button_new_with_text(SaffronText* text, bool enabled, voi
void saffron_widget_set_theme(SaffronWidget* widget, SaffronTheme* theme);
+/* very special function for special things
+ * also because i need an event hook that somewhat works
+ * for kiwihacks hackathon (wpewebkit bindings thing)
+*/
+void saffron_hook_sdl_all_events(SaffronWindow* window, bool (*callback)(SDL_Event* event), int priority);
+
#endif
diff --git a/include/saffron_event_hooks.h b/include/saffron_event_hooks.h
new file mode 100644
index 0000000..92e689e
--- /dev/null
+++ b/include/saffron_event_hooks.h
@@ -0,0 +1,13 @@
+#ifndef SAFFRON_EVENT_HOOKS_H
+#define SAFFRON_EVENT_HOOKS_H
+
+#include <SDL3/SDL.h>
+
+/* this file will not be included in saffron.h. this is an internal file for internal hooking in the event loop. */
+
+typedef struct {
+ bool (*callback)(SDL_Event* event);
+ int priority; // higher num = higher priority
+} SfInternalEventHook;
+
+#endif
diff --git a/include/saffron_window.h b/include/saffron_window.h
index 80aaa39..89bf684 100644
--- a/include/saffron_window.h
+++ b/include/saffron_window.h
@@ -2,6 +2,7 @@
#define SAFFRON_WINDOW_H
#include <SDL3/SDL.h>
+#include "saffron_event_hooks.h"
#include "saffron_widget.h"
typedef struct {
@@ -10,6 +11,8 @@ typedef struct {
SDL_Renderer *renderer;
int w, h;
const char* title;
+ SfInternalEventHook hooks[32];
+ int hook_count;
} SaffronWindow;
#endif
diff --git a/meson.build b/meson.build
index 27420ee..14aa2f0 100644
--- a/meson.build
+++ b/meson.build
@@ -12,7 +12,8 @@ sources = [
'src/saffron_widget.c',
'src/saffron_layout.c',
'src/saffron_text.c',
- 'src/saffron_button.c'
+ 'src/saffron_button.c',
+ 'src/saffron_event_hooks.c',
]
saffron_lib = static_library('saffron', sources, include_directories: inc, dependencies: deps)
@@ -26,3 +27,4 @@ saffron_dep = declare_dependency(link_with: saffron_lib, include_directories: in
test_deps += saffron_dep
executable('saffron_test', 'tests/test_main.c', dependencies: test_deps)
+executable('saffron_hooks_test', 'tests/test_hooks.c', dependencies: test_deps)
diff --git a/src/saffron_button.c b/src/saffron_button.c
index bef0018..b7db204 100644
--- a/src/saffron_button.c
+++ b/src/saffron_button.c
@@ -7,9 +7,9 @@ static void saffron_button_draw(SaffronWidget* widget, SDL_Renderer* renderer) {
SaffronTheme* theme = widget->theme;
if (!theme) return;
- SaffronColor secondary = theme->secondary;
+ SaffronColor bg = theme->bg;
SaffronColor tertiary = theme->tertiary;
- SDL_SetRenderDrawColor(renderer, secondary.r, secondary.g, secondary.b, secondary.a);
+ SDL_SetRenderDrawColor(renderer, bg.r, bg.g, bg.b, bg.a);
SDL_FRect rect = {widget->x, widget->y, widget->w, widget->h};
SDL_RenderFillRect(renderer, &rect);
@@ -17,16 +17,41 @@ static void saffron_button_draw(SaffronWidget* widget, SDL_Renderer* renderer) {
SDL_RenderRect(renderer, &rect);
}
+static void saffron_button_onclick(SaffronWidget* self) {
+ SaffronButton* btn = (SaffronButton*)self;
+ btn->callback(btn);
+}
+
SaffronButton* saffron_button_new(bool enabled, void (*callback)(SaffronButton* self), int width, int height) {
SaffronButton* button = malloc(sizeof(SaffronButton));
- saffron_widget_init((SaffronWidget*)button);
+ if (!button) return NULL;
+
+ SaffronBox* box = saffron_box_new(SAFFRON_ORIENTATION_HORIZONTAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 5, 5, 0, width, height);
+ if (!box) {
+ free(button);
+ return NULL;
+ }
+
+ memcpy(&button->base, box, sizeof(SaffronBox));
+ free(box);
- ((SaffronWidget*)button)->type = SAFFRON_WIDGET_BUTTON;
- ((SaffronWidget*)button)->draw = saffron_button_draw;
+ SaffronWidget* widget = (SaffronWidget*)button;
+ // We set it to type BOX because the layout engine needs to treat it as one: I'll remove the BUTTON enum later or make the layout engine check for both
+ widget->type = SAFFRON_WIDGET_BOX;
+ widget->draw = saffron_button_draw;
+ widget->on_click = saffron_button_onclick;
+ widget->children = NULL;
+ widget->child_count = 0;
button->callback = callback;
button->enabled = enabled;
- button->base = *saffron_box_new(SAFFRON_ORIENTATION_HORIZONTAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 5, 5, 0, width, height);
+
+ return button;
+}
+
+SaffronButton* saffron_button_new_with_text(SaffronText* text, bool enabled, void (*callback)(SaffronButton* self), int width, int height) {
+ SaffronButton* button = saffron_button_new(enabled, callback, width, height);
+ saffron_widget_add_child((SaffronWidget*)button, (SaffronWidget*)text);
return button;
}
diff --git a/src/saffron_event_hooks.c b/src/saffron_event_hooks.c
new file mode 100644
index 0000000..d3a2c43
--- /dev/null
+++ b/src/saffron_event_hooks.c
@@ -0,0 +1,19 @@
+#include "saffron_api.h"
+#include <SDL3/SDL.h>
+#include <saffron.h>
+#include <saffron_event_hooks.h>
+
+void saffron_hook_sdl_all_events(SaffronWindow* window, bool (*callback)(SDL_Event* event), int priority) {
+ window->hooks[window->hook_count].callback = callback;
+ window->hooks[window->hook_count].priority = priority;
+ window->hook_count++;
+ for (int i = 0; i < window->hook_count; i++) {
+ for (int j = i + 1; j < window->hook_count; j++) {
+ if (window->hooks[j].priority > window->hooks[i].priority) {
+ SfInternalEventHook tmp = window->hooks[i];
+ window->hooks[i] = window->hooks[j];
+ window->hooks[j] = tmp;
+ }
+ }
+ }
+}
diff --git a/src/saffron_window.c b/src/saffron_window.c
index 41bc050..34da341 100644
--- a/src/saffron_window.c
+++ b/src/saffron_window.c
@@ -14,6 +14,8 @@ SaffronWindow* saffron_window_new(const char* title, int w, int h) {
window->title = title;
window->w = w;
window->h = h;
+ memset(window->hooks, 0, sizeof(window->hooks));
+ window->hook_count = 0;
Uint32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
window->sdl_window = SDL_CreateWindow(title, w, h, flags);
@@ -81,6 +83,10 @@ void saffron_window_main(SaffronWindow *window) {
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
handle_window_resized(&event, window);
}
+ for (int i = 0; i < window->hook_count; i++) {
+ bool consumed = window->hooks[i].callback(&event);
+ if (consumed) break;
+ }
}
SDL_SetRenderDrawColor(window->renderer, 0, 0, 0, 255);
diff --git a/tests/test_hooks.c b/tests/test_hooks.c
new file mode 100644
index 0000000..ad56aa9
--- /dev/null
+++ b/tests/test_hooks.c
@@ -0,0 +1,36 @@
+#include "saffron_api.h"
+#include <saffron.h>
+#include <SDL3/SDL.h>
+#include <stdio.h>
+
+bool hook_callback(SDL_Event* event) {
+ printf("got an event!\n");
+ return false; // we didnt consume the event
+}
+
+bool hook_callback_2(SDL_Event* event) {
+ printf("second hook got an event!\n");
+ return true; // we consumed the event
+}
+
+bool hook_callback_3(SDL_Event* event) {
+ printf("you should never see this, a hook with higher priority (hook_callback_2) should have consumed this event\n");
+ return false;
+}
+
+int main() {
+ saffron_init();
+
+ SaffronWindow* window = saffron_window_new("Saffron hooks test", 800, 600);
+
+ saffron_hook_sdl_all_events(window, hook_callback, 999);
+ saffron_hook_sdl_all_events(window, hook_callback_2, 2);
+ saffron_hook_sdl_all_events(window, hook_callback_3, 1);
+
+ saffron_window_main(window);
+
+ saffron_window_free(window);
+ saffron_quit();
+
+ return 0;
+}
diff --git a/tests/test_main.c b/tests/test_main.c
index cb92189..087b32a 100644
--- a/tests/test_main.c
+++ b/tests/test_main.c
@@ -31,6 +31,10 @@ void my_test_onclick(SaffronWidget* self) {
printf("clicked!\n");
}
+static void button_click_handler(SaffronButton* self) {
+ printf("button clicked!\n");
+}
+
int main(void) {
saffron_init();
@@ -61,13 +65,12 @@ int main(void) {
TTF_Font* font = TTF_OpenFont("/usr/share/fonts/fantasque-sans-mono/FantasqueSansMono-Regular.otf", 24);
SaffronText* test3 = saffron_text_new("Mangoes", font);
- /* become lunatic, add custom clickhandler to.. text????????????? */
- ((SaffronWidget*)test3)->on_click = my_test_onclick;
+ SaffronButton* btn = saffron_button_new_with_text(test3, true, &button_click_handler, 200, 150);
saffron_widget_add_child(window->root, test);
saffron_widget_add_child(window->root, box);
saffron_widget_add_child(box, test2);
- saffron_widget_add_child(box, (SaffronWidget*)test3);
+ saffron_widget_add_child(window->root, (SaffronWidget*)btn);
saffron_window_main(window);