From 7d92468a5d298ec6dd6455482ff0521efecf9541 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Fri, 14 Feb 2025 17:30:28 +0100 Subject: Adjust wasm code and examples for new features --- Dockerfile | 2 +- examples/echo.c | 4 +- examples/graph.c | 54 ++++++++------- examples/sinewave.c | 8 +-- examples/ui.c | 45 ++++++------ index.htm | 27 ++++---- reduced_system_layer.c | 183 +++++++++++++++++++++++-------------------------- 7 files changed, 158 insertions(+), 165 deletions(-) diff --git a/Dockerfile b/Dockerfile index 97577f1..d783d81 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ RUN apk add clang lld COPY examples /usr/examples COPY reduced_system_layer.c /usr/reduced_system_layer.c COPY graphics.c /usr/graphics.c -RUN clang -D NDEBUG -O3 --target=wasm32 -nostdlib -fno-builtin -mbulk-memory -Wl,--no-entry,--allow-undefined -o /usr/index.wasm /usr/examples/julia_set.c +RUN clang -g --target=wasm32 -nostdlib -fno-builtin -mbulk-memory -Wl,--no-entry,--allow-undefined -o /usr/index.wasm /usr/examples/julia_set.c FROM nginx:alpine EXPOSE 80 diff --git a/examples/echo.c b/examples/echo.c index 1671be7..7d25001 100644 --- a/examples/echo.c +++ b/examples/echo.c @@ -43,7 +43,7 @@ i32 main(i32 argc, c8 **argv) { for (;;) { i64 n = network_recv( 0, - (IP_Address) { + (Network_Address) { .protocol = IPv4_UDP, .port = PORT, .v4_address = { 0, 0, 0, 0 }, @@ -77,7 +77,7 @@ i32 main(i32 argc, c8 **argv) { network_send( 0, - (IP_Address) { + (Network_Address) { .protocol = IPv4_UDP, .port = PORT, .v4_address = { 127, 0, 0, 1 }, diff --git a/examples/graph.c b/examples/graph.c index c1c84f2..75f83fa 100644 --- a/examples/graph.c +++ b/examples/graph.c @@ -61,11 +61,13 @@ void draw_node(i64 node_index) { color = (vec4_f32) { 0.f, .5f, 0.f, 1.f }; // green color fill_ellipse( - (Brush) { .color = color }, - n.x - n.radius, - n.y - n.radius, - n.radius * 2, - n.radius * 2 + color, + (Box) { + n.x - n.radius, + n.y - n.radius, + n.radius * 2, + n.radius * 2, + } ); } @@ -85,11 +87,11 @@ void draw_edge(i64 edge_index) { color = (vec4_f32) { 0.f, .5f, 0.f, 1.f }; // green color fill_line( - (Brush) { .color = color }, - n0.x, - n0.y, - n1.x, - n1.y, + color, + (vec2[2]) { + { n0.x, n0.y }, + { n1.x, n1.y }, + }, e.width ); } @@ -112,13 +114,14 @@ void update_node(i64 node_index) { Node n = world.nodes[node_index]; - world.nodes[node_index].hover = ellipse_contains( - n.x - n.radius, - n.y - n.radius, - n.radius * 2, - n.radius * 2, - g_platform.cursor_x, - g_platform.cursor_y + world.nodes[node_index].hover = hit_ellipse( + (Box) { + n.x - n.radius, + n.y - n.radius, + n.radius * 2, + n.radius * 2, + }, + (vec2) { g_platform.cursor_x, g_platform.cursor_y } ); } @@ -130,14 +133,13 @@ void update_edge(i64 edge_index) { Node n0 = world.nodes[e.src]; Node n1 = world.nodes[e.dst]; - world.edges[edge_index].hover = line_contains( - n0.x, - n0.y, - n1.x, - n1.y, + world.edges[edge_index].hover = hit_line( + (vec2[2]) { + { n0.x, n0.y }, + { n1.x, n1.y }, + }, e.width, - g_platform.cursor_x, - g_platform.cursor_y + (vec2) { g_platform.cursor_x, g_platform.cursor_y } ); } @@ -502,7 +504,7 @@ void update_and_render_frame(void) { // Render - fill_rectangle((Brush) { .color = { .7f, .8f, .9f, 1.f } }, 0, 0, g_platform.real_width, g_platform.real_height); + fill_rectangle_quick((vec4_f32) { .7f, .8f, .9f, 1.f }, (Box) { 0, 0, g_platform.real_width, g_platform.real_height }); if (adding_edge) { f64 x0 = world.nodes[adding_src].x; @@ -515,7 +517,7 @@ void update_and_render_frame(void) { y1 = world.nodes[adding_dst].y; } - fill_line((Brush) { .color = { .5f, 0.f, .5f, 1.f } }, x0, y0, x1, y1, 30); + fill_line((vec4_f32) { .5f, 0.f, .5f, 1.f }, (vec2[2]) { { x0, y0 }, { x1, y1 } }, 30); } draw_graph(); diff --git a/examples/sinewave.c b/examples/sinewave.c index 0c33803..d5072da 100644 --- a/examples/sinewave.c +++ b/examples/sinewave.c @@ -9,11 +9,11 @@ b8 ui_button(f64 x, f64 y, f64 width, f64 height) { b8 is_pressed = has_cursor && g_platform.key_down[BUTTON_LEFT]; if (is_pressed) - fill_rectangle(RGB(1.f, 1.f, 1.f), x, y, width, height); + fill_rectangle((vec4_f32) { 1.f, 1.f, 1.f, 1.f }, (Box) { x, y, width, height }); else if (has_cursor) - fill_rectangle(RGB(.8f, .8f, 0.f), x, y, width, height); + fill_rectangle((vec4_f32) { .8f, .8f, 0.f, 1.f }, (Box) { x, y, width, height }); else - fill_rectangle(RGB(.8f, .8f, .2f), x, y, width, height); + fill_rectangle((vec4_f32) { .8f, .8f, .2f, 1.f }, (Box) { x, y, width, height }); return has_cursor && g_platform.key_pressed[BUTTON_LEFT]; } @@ -22,7 +22,7 @@ void update_and_render_frame(void) { i32 num_events = handle_main_window_events(); if (num_events > 0) { - fill_rectangle(RGB(.1f, .1f, .1f), 0, 0, g_platform.frame_width, g_platform.frame_height); + fill_rectangle((vec4_f32) { .1f, .1f, .1f, 1.f }, (Box) { 0, 0, g_platform.frame_width, g_platform.frame_height }); if (ui_button(100, 100, 200, 200)) queue_primary_sound(0, PRIMARY_SOUND_SAMPLE_RATE, frames); diff --git a/examples/ui.c b/examples/ui.c index a3ca476..af9b89d 100644 --- a/examples/ui.c +++ b/examples/ui.c @@ -14,27 +14,26 @@ i64 selection = 0; void update_and_render_frame(void) { wait_main_window_events(); - Brush background = RGB(.2f, .1f, 0.f); - background.quick = 1; + vec4_f32 background = { .2f, .1f, 0.f, 1.f }; - Brush white = RGB(1.f, 1.f, 1.f); - Brush green = RGB(0.f, 1.f, 0.f); - Brush dark_green = RGB(.1f, .5f, .1f); - Brush red = RGB(1.f, 0.f, 0.f); - Brush light_red = RGB(1.f, .5f, .5f); - Brush light_green = RGB(.5f, 1.f, .5f); + vec4_f32 white = { 1.f, 1.f, 1.f, 1.f }; + vec4_f32 green = { 0.f, 1.f, 0.f, 1.f }; + vec4_f32 dark_green = { .1f, .5f, .1f, 1.f }; + vec4_f32 red = { 1.f, 0.f, 0.f, 1.f }; + vec4_f32 light_red = { 1.f, .5f, .5f, 1.f }; + vec4_f32 light_green = { .5f, 1.f, .5f, 1.f }; - fill_rectangle(background, 0, 0, g_platform.real_width, g_platform.real_height); + fill_rectangle_quick(background, (Box) { 0, 0, g_platform.real_width, g_platform.real_height }); if (g_platform.cursor_x >= 40 && g_platform.cursor_x < 100 && g_platform.cursor_y >= 40 && g_platform.cursor_y < 100) { button_0_down = g_platform.key_down[BUTTON_LEFT]; if (button_0_down) - fill_rectangle(white, 40, 40, 60, 60); + fill_rectangle(white, (Box) { 40, 40, 60, 60 }); else - fill_rectangle(green, 40, 40, 60, 60); + fill_rectangle(green, (Box) { 40, 40, 60, 60 }); } else { button_0_down = 0; - fill_rectangle(dark_green, 40, 40, 60, 60); + fill_rectangle(dark_green, (Box) { 40, 40, 60, 60 }); } if (g_platform.cursor_x >= 40 && g_platform.cursor_x < 100 && g_platform.cursor_y >= 120 && g_platform.cursor_y < 180) { @@ -42,17 +41,17 @@ void update_and_render_frame(void) { if (g_platform.key_pressed[BUTTON_LEFT]) button_1_checked = !button_1_checked; if (button_1_down) - fill_rectangle(white, 40, 120, 60, 60); + fill_rectangle(white, (Box) { 40, 120, 60, 60 }); else if (button_1_checked) - fill_rectangle(light_red, 40, 120, 60, 60); + fill_rectangle(light_red, (Box) { 40, 120, 60, 60 }); else - fill_rectangle(light_green, 40, 120, 60, 60); + fill_rectangle(light_green, (Box) { 40, 120, 60, 60 }); } else { button_1_down = 0; if (button_1_checked) - fill_rectangle(red, 40, 120, 60, 60); + fill_rectangle(red, (Box) { 40, 120, 60, 60 }); else - fill_rectangle(green, 40, 120, 60, 60); + fill_rectangle(green, (Box) { 40, 120, 60, 60 }); } f64 w = g_platform.real_width / 2.0; @@ -66,7 +65,7 @@ void update_and_render_frame(void) { g_platform.cursor_y >= y0 && g_platform.cursor_y < y0 + h) color = (vec4_f32) { 1.f, 1.f, 1.f, 1.f }; - for (i64 i = 0; i < g_platform.input_size; ++i) + for (i64 i = 0; i < g_platform.input_len; ++i) if (g_platform.input[i].ctrl) switch (g_platform.input[i].key) { case KEY_V: { @@ -104,7 +103,7 @@ void update_and_render_frame(void) { len += utf8_write(text[i0 + i], buf + len); if (len > 0) - p_clipboard_write_text(len, buf); + write_clipboard_text(len, buf); for (i64 i = 0; i1 + i < text_len; ++i) text[i0 + i] = text[i1 + i]; @@ -123,7 +122,7 @@ void update_and_render_frame(void) { len += utf8_write(text[i0 + i], buf + len); if (len > 0) - p_clipboard_write_text(len, buf); + write_clipboard_text(len, buf); } break; default:; @@ -222,9 +221,9 @@ void update_and_render_frame(void) { text[i] = g_platform.drop_files[0].data[i]; } - draw_text_area(RGB(0.f, 0.f, 0.f), x0 + 8, y0 - 8, w, h, 10., 10., text_len, text); - draw_text_area((Brush) { .color = color, }, x0, y0, w, h, 10., 10., text_len, text); - draw_text_cursor((Brush) { .xor_color = 1, .color = { 1.f, 1.f, 1.f, 1.f }, }, x0, y0, w, h, 10., 10., cursor, selection, text_len, text); + draw_text_cursor((vec4_f32) { 1.f, 1.f, 1.f, 1.f }, (Box) { x0, y0, w, h }, (vec2) { 10., 10. }, text_len, text, cursor, selection); + draw_text_area((vec4_f32) { 0.f, 0.f, 0.f, 1.f }, (Box) { x0 + 8, y0 - 8, w, h }, (vec2) { 10., 10. }, text_len, text); + draw_text_area(color, (Box) { x0, y0, w, h }, (vec2) { 10., 10. }, text_len, text); render_main_window_frame(); } diff --git a/index.htm b/index.htm index 2e3ebe8..f94bdca 100644 --- a/index.htm +++ b/index.htm @@ -43,7 +43,7 @@ text_buffer : text_buffer, }); }, - current_time_in_milliseconds : () => { return BigInt(Date.now()); }, + current_utc_time_in_milliseconds : () => { return BigInt(Date.now()); }, floor : Math.floor, ceil : Math.ceil, @@ -76,8 +76,6 @@ this.sound_buffer_address = program.exports.js_sound_buffer(); this.pixels_address = program.exports.js_pixels(); - this.max_drop_size = program.exports.js_max_drop_size(); - this.drop_address = program.exports.js_drop_buffer(); this.frames = new Float32Array( this.memory_buffer, @@ -160,8 +158,8 @@ if (this.program === undefined) return; - let address = this.program.exports.js_clipboard_buffer(ev.bytes.length); - let len = this.program.exports.js_clipboard_size(); + let address = this.program.exports.js_clipboard_text(ev.bytes.length); + let len = this.program.exports.js_clipboard_text_len(); new Uint8Array(this.memory_buffer, address, len).set(ev.bytes.subarray(0, len)); @@ -187,14 +185,19 @@ return; for (let f of ev.files) { - if (f.name.byteLength + f.data.byteLength > this.max_drop_size) { + let ok = this.program.exports.js_drop(f.name.byteLength + 1, f.data.byteLength); + + if (ok == 0) { console.error("File too big"); - continue; + break; } + let name_address = this.program.exports.js_drop_name(); + let data_address = this.program.exports.js_drop_data(); + new Uint8Array( this.memory_buffer, - this.drop_address, + name_address, f.name.byteLength ).set( new Uint8Array(f.name) @@ -202,13 +205,11 @@ new Uint8Array( this.memory_buffer, - this.drop_address + f.name.byteLength, + data_address, f.data.byteLength ).set( new Uint8Array(f.data) ); - - this.program.exports.js_drop(f.name.byteLength, f.data.byteLength); } }, }; @@ -275,8 +276,8 @@ wasm, { env : { - write_clipboard_impl : () => {}, - current_time_in_milliseconds : () => {}, + write_clipboard_impl : () => {}, + current_utc_time_in_milliseconds : () => {}, floor : () => {}, ceil : () => {}, diff --git a/reduced_system_layer.c b/reduced_system_layer.c index 2b9ae9e..ae28109 100755 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -1461,7 +1461,8 @@ static void drop_files_set_num_(i64 num) { resize_dynamic_array_exact(&g_platform.num_drop_files, (void **) &g_platform.drop_files, sizeof *g_platform.drop_files, num); - mem_set_(g_platform.drop_files + prev_num, 0, sizeof *g_platform.drop_files * (g_platform.num_drop_files - prev_num)); + if (prev_num < g_platform.num_drop_files) + mem_set_(g_platform.drop_files + prev_num, 0, sizeof *g_platform.drop_files * (g_platform.num_drop_files - prev_num)); } static void drop_files_set_name_(i64 index, i64 name_len, c8 *name) { @@ -1478,7 +1479,8 @@ static void drop_files_set_name_(i64 index, i64 name_len, c8 *name) { Drop_File *f = g_platform.drop_files + index; resize_dynamic_array_exact(&f->name_len, (void **) &f->name, 1, name_len); - mem_cpy_(f->name, name, f->name_len); + if (name != NULL) + mem_cpy_(f->name, name, f->name_len); } static void drop_files_set_data_(i64 index, i64 data_size) { @@ -1517,7 +1519,7 @@ static i8 pixel_size_update_(i64 real_width, i64 real_height) { resize_dynamic_array_exact(&g_platform.num_pixels, (void **) &g_platform.pixels, sizeof *g_platform.pixels, width * height); if (g_platform.num_pixels < width * height) LOG_ERROR("Failed to allocate %lld x %lld pixel buffer.", width, height); - height = g_platform.num_pixels / width; + height = width <= 0 ? 0 : g_platform.num_pixels / width; if (g_platform.frame_width != width || g_platform.frame_height != height) { size_changed = 1; @@ -1532,7 +1534,7 @@ static i8 pixel_size_update_(i64 real_width, i64 real_height) { if (_internal_pixels_len < internal_width * internal_height) LOG_ERROR("Failed to allocate %lld x %lld internal pixel buffer.", internal_width, internal_height); _internal_width = real_width; - _internal_height = min2_i32_(_internal_pixels_len / real_width, real_height); + _internal_height = real_width <= 0 ? 0 : min2_i32_(_internal_pixels_len / real_width, real_height); return size_changed; } @@ -1673,6 +1675,18 @@ static void cleanup_pixel_buffers_(void) { resize_dynamic_array_exact(&g_platform.num_pixels, (void **) &g_platform.pixels, sizeof *g_platform.pixels, 0); } +static void store_clipboard_text_(i64 size, c8 *data) { + if (size < 0 || data == NULL) + return; + + resize_dynamic_array_exact(&g_platform.clipboard_text_len, (void **) &g_platform.clipboard_text, 1, size + 1); + + i64 len = g_platform.clipboard_text_len - 1; + mem_cpy_(g_platform.clipboard_text, data, len); + if (len >= 0) + g_platform.clipboard_text[len] = '\0'; +} + // ================================================================ // // Unix @@ -3556,15 +3570,13 @@ void render_main_window_frame(void) { } void write_clipboard_text(i64 size, c8 *data) { - XSetSelectionOwner(_display, _clipboard, _window, CurrentTime); + if (size < 0 || data == NULL) + return; - resize_dynamic_array_exact(&g_platform.clipboard_text_len, (void **) &g_platform.clipboard_text, 1, size + 1); + store_clipboard_text_(size, data); - i64 len = g_platform.clipboard_text_len - 1; - if (len >= 0) { - mem_cpy_(g_platform.clipboard_text, data, len); - g_platform.clipboard_text[len] = '\0'; - } + if (g_platform.clipboard_text_len > 0) + XSetSelectionOwner(_display, _clipboard, _window, CurrentTime); } b8 x11_screenshot_(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) { @@ -3765,10 +3777,8 @@ __attribute__((export_name("js_num_sound_channels"))) i32 js_num_sound_channels( #if defined(__wasm__) -static i32 _frame_width = 0; -static i32 _frame_height = 0; static i32 _num_events = 0; -static i32 _input_size = 0; +static i32 _input_len = 0; static i32 _cursor_dx = 0; static i32 _cursor_dy = 0; static f64 _wheel_dx = 0; @@ -3779,12 +3789,9 @@ static i64 _sound_read = 0; static b8 _files_dragged = 0; static b8 _files_dropped = 0; -static c8 _href [4096] = {0}; -static u32 _pixels_scaled [MAX_NUM_PIXELS] = {0}; -static u32 _internal_pixels [MAX_NUM_PIXELS] = {0}; -static b8 _key_pressed [MAX_NUM_KEYS] = {0}; -static f32 _sound_buffer [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0}; -static u8 _drop_buffer [DROP_FILES_BUFFER_SIZE] = {0}; +static c8 _href [4096] = {0}; +static b8 _key_pressed [MAX_NUM_KEYS] = {0}; +static f32 _sound_buffer [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0}; void shutdown_all_systems(void) { g_platform.done = 1; @@ -3838,10 +3845,17 @@ void init_main_window(void) { } i32 handle_main_window_events(void) { - if (g_platform.files_dropped) + if (g_platform.files_dropped) { + // NOTE: We won't be able to drop files at each + // of 2 sequential frames. + drop_files_clean_(); - g_platform.input_size = _input_size; + _files_dragged = 0; + _files_dropped = 0; + } + + g_platform.input_len = _input_len; g_platform.cursor_dx = _cursor_dx; g_platform.cursor_dy = _cursor_dy; g_platform.wheel_dx = _wheel_dx; @@ -3849,11 +3863,11 @@ i32 handle_main_window_events(void) { g_platform.files_dragged = _files_dragged; g_platform.files_dropped = _files_dropped; - _input_size = 0; - _cursor_dx = 0; - _cursor_dy = 0; - _wheel_dx = 0; - _wheel_dy = 0; + _input_len = 0; + _cursor_dx = 0; + _cursor_dy = 0; + _wheel_dx = 0; + _wheel_dy = 0; if (_files_dropped) { _files_dragged = 0; @@ -3877,36 +3891,7 @@ i32 wait_main_window_events(void) { } void render_main_window_frame(void) { - if (_frame_width == g_platform.frame_width && _frame_height == g_platform.frame_height) { - i64 size = g_platform.frame_width * g_platform.frame_height; - if (size > g_platform.num_pixels) - size = g_platform.num_pixels; - if (size > _internal_pixels_len) - size = _internal_pixels_len; - - for (i64 i = 0; i < size; ++i) - _internal_pixels[i] = 0xff000000u | rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x }); - } else { - i64 size = g_platform.frame_width * g_platform.frame_height; - if (size > g_platform.num_pixels) - size = g_platform.num_pixels; - if (size > _pixels_scaled_len) - size = _pixels_scaled_len; - - for (i64 i = 0; i < size; ++i) - _pixels_scaled[i] = rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x }); - - for (i64 j = 0; j < _frame_height; ++j) { - i64 j0 = (j * g_platform.frame_height) / _frame_height; - if ((j0 + 1) * _frame_width > _internal_pixels_len) break; - for (i64 i = 0; i < _frame_width; ++i) { - i64 i0 = (i * g_platform.frame_width) / _frame_width; - i64 n0 = j0 * g_platform.frame_width + i0; - if (n0 > _pixels_scaled_len) break; - _internal_pixels[j * _frame_width + i] = 0xff000000u | _pixels_scaled[n0]; - } - } - } + convert_pixels_for_window_(); } void write_clipboard_text_impl(i32 size, c8 *data); @@ -3914,14 +3899,11 @@ void write_clipboard_text_impl(i32 size, c8 *data); void write_clipboard_text(i64 size, c8 *data) { if (size < 0 || data == NULL) return; - if (size > MAX_CLIPBOARD_SIZE) - size = MAX_CLIPBOARD_SIZE; - g_platform.clipboard_size = size; - for (i64 i = 0; i < size; ++i) - g_platform.clipboard[i] = data[i]; + store_clipboard_text_(size, data); - write_clipboard_text_impl((i32) size, data); + if (g_platform.clipboard_text_len > 0) + write_clipboard_text_impl((i32) g_platform.clipboard_text_len - 1, data); } void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) { @@ -4005,12 +3987,7 @@ __attribute__((export_name("js_pixels"))) void *js_pixels(void) { __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height, i32 num_samples) { i64 frame_time = current_utc_time_in_milliseconds(); - if (frame_width > 0 && frame_height > 0 && frame_width * frame_height <= MAX_NUM_PIXELS) { - _frame_width = frame_width; - _frame_height = frame_height; - } - - _num_events += pixel_size_update_(_frame_width, _frame_height); + _num_events += pixel_size_update_(frame_width, frame_height); g_platform.done = 0; @@ -4026,7 +4003,7 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram for (i64 i = 0; i < num_samples; ++i) { i64 n = (_sound_read + i * NUM_PRIMARY_SOUND_CHANNELS + j) % MAX_NUM_PRIMARY_SOUND_FRAMES; _sound_buffer[j * num_samples + i] = _sound_ring[n]; - _sound_ring[n] = 0.f; + _sound_ring[n] = 0.f; } _sound_read = (_sound_read + num_samples * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES; @@ -4068,8 +4045,12 @@ __attribute__((export_name("js_keydown"))) void js_keydown(u32 key, u32 mod, u32 g_platform.key_down[MOD_SHIFT] = (mod & 2) ? 1 : 0; g_platform.key_down[MOD_ALT] = (mod & 4) ? 1 : 0; g_platform.key_down[MOD_META] = (mod & 8) ? 1 : 0; - if (g_platform.input_size < MAX_INPUT_SIZE) - g_platform.input[_input_size++] = (Input_Key) { + + i64 n = g_platform.input_len; + resize_dynamic_array_capacity(&g_platform.input_len, &g_platform.input_capacity, (void **) &g_platform.input, sizeof *g_platform.input, n + 1); + + if (n < g_platform.input_len) + g_platform.input[n] = (Input_Key) { .ctrl = (mod & 1) ? 1 : 0, .shift = (mod & 2) ? 1 : 0, .alt = (mod & 4) ? 1 : 0, @@ -4094,17 +4075,15 @@ __attribute__((export_name("js_wheel"))) void js_wheel(f64 delta_x, f64 delta_y) _wheel_dy += delta_y * MOUSE_WHEEL_FACTOR; } -__attribute__((export_name("js_clipboard_size"))) i32 js_clipboard_size(void) { - return g_platform.clipboard_size; +__attribute__((export_name("js_clipboard_text_len"))) i32 js_clipboard_text_len(void) { + return g_platform.clipboard_text_len; } -__attribute__((export_name("js_clipboard_buffer"))) void *js_clipboard_buffer(i32 len) { +__attribute__((export_name("js_clipboard_text"))) void *js_clipboard_text(i32 len) { if (len < 0) len = 0; - if (len > MAX_CLIPBOARD_SIZE) - len = MAX_CLIPBOARD_SIZE; - g_platform.clipboard_size = len; - return g_platform.clipboard; + resize_dynamic_array_exact(&g_platform.clipboard_text_len, (void **) &g_platform.clipboard_text, 1, len); + return g_platform.clipboard_text; } __attribute__((export_name("js_dragenter"))) void js_dragenter(void) { @@ -4115,30 +4094,42 @@ __attribute__((export_name("js_dragleave"))) void js_dragleave(void) { _files_dragged = 0; } -__attribute__((export_name("js_max_drop_size"))) i32 js_max_drop_size(void) { - return sizeof _drop_buffer; -} - -__attribute__((export_name("js_drop_buffer"))) void *js_drop_buffer(void) { - return _drop_buffer; -} - -__attribute__((export_name("js_drop"))) void js_drop(i32 name_len, i32 data_size) { - if (name_len + data_size > (i32) sizeof _drop_buffer) { - LOG_ERROR("File too big."); - return; - } - +__attribute__((export_name("js_drop"))) i32 js_drop(i32 name_len, i32 data_size) { i64 n = g_platform.num_drop_files; drop_files_set_num_(n + 1); - drop_files_set_name_(n, name_len, (c8 *) _drop_buffer); + + if (n >= g_platform.num_drop_files) + return 0; + + drop_files_set_name_(n, name_len, NULL); drop_files_set_data_(n, data_size); - for (i64 i = 0; i < data_size; ++i) - g_platform.drop_files[n].data[i] = _drop_buffer[name_len + i]; + Drop_File *f = g_platform.drop_files + n; + + if (f->name_len != name_len || f->data_size != data_size) { + drop_files_set_name_(n, 0, NULL); + drop_files_set_data_(n, 0); + drop_files_set_num_(n); + return 0; + } + + mem_set_(f->name, 0, name_len); _files_dropped = 1; + return 1; +} + +__attribute__((export_name("js_drop_name"))) void *js_drop_name(void) { + if (g_platform.num_drop_files <= 0) + return NULL; + return g_platform.drop_files[g_platform.num_drop_files - 1].name; +} + +__attribute__((export_name("js_drop_data"))) void *js_drop_data(void) { + if (g_platform.num_drop_files <= 0) + return NULL; + return g_platform.drop_files[g_platform.num_drop_files - 1].data; } #endif // defined(__wasm__) -- cgit v1.2.3