summaryrefslogtreecommitdiff
path: root/Peak/src/p_emscripten.c
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 00:56:24 +0100
committerVasco <[email protected]>2026-08-24 00:56:24 +0100
commit5dc2716abd43166cd65133625f408ad36a6623b3 (patch)
tree19d89b838206b6bb11cc0b9f88311d855999d447 /Peak/src/p_emscripten.c
parentdc96fcd771bea09d726a760266739906e95c09a6 (diff)
Peak 0.4.0 and Draw
Diffstat (limited to 'Peak/src/p_emscripten.c')
-rw-r--r--Peak/src/p_emscripten.c194
1 files changed, 172 insertions, 22 deletions
diff --git a/Peak/src/p_emscripten.c b/Peak/src/p_emscripten.c
index dc558f5..f79f575 100644
--- a/Peak/src/p_emscripten.c
+++ b/Peak/src/p_emscripten.c
@@ -1,38 +1,188 @@
+#include <emscripten.h>
+#include <emscripten/html5.h>
#include <stdlib.h>
#include <string.h>
-#include <stdbool.h>
+#include <stdint.h>
-#define PEAK_CANVAS "#PeakCanvas"
+EM_JS(void, peak_web_dom_open, (const char *id, int w, int h), {
+ var name = UTF8ToString(id);
+ var c = document.getElementById(name);
+ if (!c) {
+ c = document.createElement('canvas');
+ c.id = name;
+ document.body.appendChild(c);
+ }
+ c.width = w;
+ c.height = h;
+ c.tabIndex = 0;
+ c.focus();
+});
-static PeakKeyCode map_key(const char *code);
-static PeakKeyMod map_mod(const EmscriptenKeyboardEvent *keyEvent);
-static EM_BOOL key_callback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
-static EM_BOOL mouse_callback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
-static EM_BOOL resize_callback(int eventType, const EmscriptenUiEvent *uiEvent, void *userData);
+EM_JS(void, peak_web_dom_present, (const char *id, int w, int h, uintptr_t pixels), {
+ var c = document.getElementById(UTF8ToString(id));
+ if (!c) return;
+ var ctx = c.getContext('2d');
+ if (c.width !== w || c.height !== h) {
+ c.width = w;
+ c.height = h;
+ }
+ var img = ctx.createImageData(w, h);
+ img.data.set(HEAPU8.subarray(pixels, pixels + w * h * 4));
+ ctx.putImageData(img, 0, 0);
+});
-void
-peak_platform_window_open()
+struct peak_web_win {
+ char name[64];
+ uint32_t width, height;
+ PeakQ q;
+ uint32_t buffer[];
+};
+
+struct peak_window_internal_t {
+ struct peak_web_win *w;
+};
+
+static void
+peak_web_sel(const char *name, char *out, size_t n)
+{
+ out[0] = '#';
+ strncpy(out + 1, name, n - 2);
+ out[n - 1] = 0;
+}
+
+static PeakKeyCode
+peak_web_key_map(const char *code)
+{
+ if (code[0] == 'K' && code[1] == 'e' && code[2] == 'y' && code[3] >= 'A' && code[3] <= 'Z' && code[4] == 0)
+ return (PeakKeyCode)(PEAK_KEY_A + (code[3] - 'A'));
+ if (!strcmp(code, "ArrowUp")) return PEAK_KEY_UP;
+ if (!strcmp(code, "ArrowDown")) return PEAK_KEY_DOWN;
+ if (!strcmp(code, "ArrowLeft")) return PEAK_KEY_LEFT;
+ if (!strcmp(code, "ArrowRight")) return PEAK_KEY_RIGHT;
+ if (!strcmp(code, "Space")) return PEAK_KEY_SPACE;
+ if (!strcmp(code, "Escape")) return PEAK_KEY_ESCAPE;
+ if (!strcmp(code, "Enter")) return PEAK_KEY_ENTER;
+ return PEAK_KEY_UNKNOWN;
+}
+
+static EM_BOOL
+peak_web_key(int type, const EmscriptenKeyboardEvent *e, void *ud)
+{
+ PeakEvent ev = {0};
+ ev.type = (type == EMSCRIPTEN_EVENT_KEYDOWN) ? PEAK_EVENT_KEY_DOWN : PEAK_EVENT_KEY_UP;
+ ev.key.key = peak_web_key_map(e->code);
+ ev.key.mod = e->ctrlKey ? PEAK_KEYMOD_CTRL : e->altKey ? PEAK_KEYMOD_ALT : e->shiftKey ? PEAK_KEYMOD_SHIFT : 0;
+ peak_q_push(&((struct peak_web_win *)ud)->q, ev);
+ return EM_TRUE;
+}
+
+static EM_BOOL
+peak_web_mouse(int type, const EmscriptenMouseEvent *e, void *ud)
+{
+ PeakEvent ev = {0};
+ ev.type = PEAK_EVENT_POINTER;
+ ev.pointer.x = (float)e->targetX;
+ ev.pointer.y = (float)e->targetY;
+ if (type == EMSCRIPTEN_EVENT_MOUSEDOWN)
+ ev.pointer.state = PEAK_POINTER_PRESSED;
+ else if (type == EMSCRIPTEN_EVENT_MOUSEUP)
+ ev.pointer.state = PEAK_POINTER_RELEASED;
+ else
+ ev.pointer.state = PEAK_POINTER_MOVED;
+ if (type == EMSCRIPTEN_EVENT_MOUSEMOVE) {
+ ev.pointer.type = (e->buttons & 4) ? PEAK_POINTER_MIDDLE :
+ (e->buttons & 2) ? PEAK_POINTER_RIGHT : PEAK_POINTER_LEFT;
+ } else {
+ ev.pointer.type = (e->button == 1) ? PEAK_POINTER_MIDDLE :
+ (e->button == 2) ? PEAK_POINTER_RIGHT : PEAK_POINTER_LEFT;
+ }
+ peak_q_push(&((struct peak_web_win *)ud)->q, ev);
+ return EM_TRUE;
+}
+
+static void
+peak_web_listen(struct peak_web_win *w, int on)
+{
+ char sel[66];
+ peak_web_sel(w->name, sel, sizeof sel);
+ emscripten_set_keydown_callback(sel, w, EM_TRUE, on ? peak_web_key : NULL);
+ emscripten_set_keyup_callback(sel, w, EM_TRUE, on ? peak_web_key : NULL);
+ emscripten_set_mousedown_callback(sel, w, EM_TRUE, on ? peak_web_mouse : NULL);
+ emscripten_set_mouseup_callback(sel, w, EM_TRUE, on ? peak_web_mouse : NULL);
+ emscripten_set_mousemove_callback(sel, w, EM_TRUE, on ? peak_web_mouse : NULL);
+}
+
+static int
+peak_platform_init(void)
+{
+ return 1;
+}
+
+static void
+peak_platform_quit(void)
+{
+}
+
+static PeakWindowInternal
+peak_platform_window_open(const char *name, uint32_t width, uint32_t height, uint32_t flags)
+{
+ PeakWindowInternal intern = {0};
+ struct peak_web_win *w;
+
+ (void)flags;
+
+ w = calloc(1, sizeof *w + (size_t)width * height * sizeof *w->buffer);
+ if (!w)
+ return intern;
+ strncpy(w->name, name, sizeof w->name - 1);
+ w->width = width;
+ w->height = height;
+
+ peak_web_dom_open(w->name, (int)width, (int)height);
+
+ peak_web_listen(w, 1);
+ intern.w = w;
+ return intern;
+}
+
+static void
+peak_platform_window_close(PeakWindowInternal *intern)
{
- emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_TRUE, key_callback);
- emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_TRUE, key_callback);
- emscripten_set_mousedown_callback(PEAK_CANVAS, NULL, EM_TRUE, mouse_callback);
- emscripten_set_mouseup_callback(PEAK_CANVAS, NULL, EM_TRUE, mouse_callback);
- emscripten_set_mousemove_callback(PEAK_CANVAS, NULL, EM_TRUE, mouse_callback);
- emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_TRUE, resize_callback);
+ struct peak_web_win *w;
+ if (!intern || !intern->w)
+ return;
+ w = intern->w;
+ peak_web_listen(w, 0);
+ free(w);
+ intern->w = NULL;
}
-void
-peak_platform_window_close()
+static uint32_t *
+peak_platform_window_buffer(PeakWindowInternal *intern, size_t *width, size_t *height)
{
+ struct peak_web_win *w = intern ? intern->w : NULL;
+ if (!w) {
+ *width = 0;
+ *height = 0;
+ return NULL;
+ }
+ *width = w->width;
+ *height = w->height;
+ return w->buffer;
}
-uint32_t*
-peak_platform_window_buffer(size_t *width, size_t *height)
+static void
+peak_platform_window_present(PeakWindowInternal *intern)
{
+ struct peak_web_win *w = intern ? intern->w : NULL;
+ if (!w)
+ return;
+ peak_web_dom_present(w->name, (int)w->width, (int)w->height, (uintptr_t)w->buffer);
}
-bool
-peak_platform_epoll(PeakEvent *ev)
+static bool
+peak_platform_epoll(PeakWindowInternal *intern, PeakEvent *ev)
{
- return 0;
+ struct peak_web_win *w = intern ? intern->w : NULL;
+ return w ? peak_q_pop(&w->q, ev) : 0;
}