std1.0.0-beta-7 SafeC docs

Source gui/gui_web.h

View in the repository

#pragma once
// SafeC Standard Library — GUI: the WebAssembly <canvas> backend.
//
// On a wasm32/wasm64 target std/gui's platform backend is the browser:
// every GuiWindow is a <canvas> element of the page (or an OffscreenCanvas
// where there is no document), and everything else in std/gui — the
// canvas, text, widgets, GuiApp with its timers and animation frames —
// works unchanged on top of it. The host side is std/gui/gui_web.js, an ES
// module shipped next to this header (see its header comment):
//
//   import { loadSafeCGui } from "./gui_web.js";
//   const app = await loadSafeCGui(fetch("app.wasm"), { entry: "start" });
//
// A browser must not block, so a program doesn't call GuiApp::run(): its
// entry point (an export_name function the glue calls once) opens the
// windows, then hands the app to gui_web_run(), which returns at once; the
// glue then calls GuiApp::pump(0) once per requestAnimationFrame until it
// returns 0 (the last window closed or quit()):
//
//   static struct GuiApp gApp;                 // must outlive start()
//   __attribute__((export_name("start")))
//   int start() {
//       gApp = GuiApp::new();
//       ?&GuiWindow w = gApp.open_window("Hello", 480, 320);
//       ...
//       gui_web_run(&gApp);
//       return 0;
//   }
//
// What maps to what:
//   windows     windows: "canvas" (default) — each window a <canvas>: the
//               glue's 'canvas' option picks it (an element, a selector, or
//               a function (index, title) => canvas), else the next unused
//               canvas[data-safec-gui] of the page, else a new <canvas>
//               appended to <body>. Its CSS size is the window's logical
//               size and its backing store that times devicePixelRatio
//               (hiDpi), so drawing is sharp; with the 'fit' option (or a
//               data-safec-fit attribute) the canvas keeps the size the
//               page's CSS gives it and follows it (ResizeObserver) —
//               GUI_EVENT_RESIZE, as a window would. windows: "frames" —
//               each window a positioned <div class="safec-gui-window"> in
//               a container, with a title bar (drag it: GUI_EVENT_MOVE,
//               set_position()/pos_x() work; its × : GUI_EVENT_CLOSE), a
//               resize grip honoring the size limits, raised on a click.
//   presenting  putImageData of the damaged rectangle, straight from the
//               module's memory (premultiplied pixels converted to
//               ImageData's straight alpha on the way) — or, with the
//               page's present: "webgl" option or GUI_PRESENT_GPU, WebGL2
//               (else WebGL1): the damaged rectangle uploaded into a
//               texture and drawn as one quad (gui_gpu_web_wasm.sc), back
//               to putImageData if there is no WebGL or the context is lost.
//   input       pointer events (with pointer capture while a button is
//               down), wheel (pixel/line/page deltas to lines); keyboard
//               focus is real DOM focus on a hidden <textarea> per window
//               (a click on the canvas focuses it): KeyboardEvent.code/key
//               to GUI_KEY_* and the typed character, and text that comes
//               without a key — IME composition, virtual keyboards,
//               context-menu pastes — as GUI_EVENT_CHAR.
//   HiDPI       devicePixelRatio, followed when it changes (zoom, another
//               display): GUI_EVENT_SCALE.
//   clipboard   gui_clipboard_set_text() writes navigator.clipboard (and the
//               copy event a Ctrl/Cmd+C shortcut fires); gui_clipboard_get_text()
//               returns the text of the last paste event or of the last
//               copy — the glue holds a Ctrl/Cmd+V keydown back until its
//               paste event arrived, so a paste shortcut sees the pasted
//               text. Reading the system clipboard any other way needs a
//               permission browsers don't grant silently.
//   cursors     CSS cursor on the canvas.
//   a11y        canvases are role="img" labelled with the window title, the
//               hidden input carries it too, and gui_web_announce() speaks
//               through an aria-live region.
//   DOM         gui_web_window_element()/gui_web_mount() trade elements with
//               std/wasm/dom.h, so a page mixes DOM and std/gui windows.
//   clock       performance.now(); timers fire from the frame loop.
// Files: fopen()/fread() read the glue's 'files' option (fetchFiles()), e.g.
// fonts at the paths std/gui looks in; the TrueType stack's embedded
// fallback face is there without any. 'safeguard bundle --target wasm32'
// writes build/<name>.web/: the module, this glue and a page.

#include <std/gui/gui.h>
#include <std/gui/gui_app.h>

namespace std {

// Lets the JS glue drive 'app' from requestAnimationFrame: one
// app.pump(0) per frame until it returns 0. Returns at once. 'app' must
// stay alive (a static or heap object) after the caller returns.
void gui_web_run(&GuiApp app);

// Screen readers: says 'text' through the page's aria-live region (e.g. a
// status change your UI only draws).
void gui_web_announce(const &char text);

// std/wasm/dom.h interop (the page loaded the module through safec_dom.js's
// loadSafeC, or passed its glue as the domGlue option): the window's
// element — its frame in "frames" mode, else its <canvas> — as a dom.h
// handle (-1 without the DOM glue), to style it or put DOM elements next
// to it; and moving the window's element into DOM element 'parent'
// (1 = done).
int gui_web_window_element(const &GuiWindow win);
int gui_web_mount(&GuiWindow win, int parent);

} // namespace std