v0.1.0 โ€” In Development

SylinthUI

SylinthUI is a Rust-based cross-platform UI framework that renders interfaces using native WebView engines (WebView2 on Windows, WebKit on macOS), designed for real-time overlay and control panel systems.

๐Ÿ’ก What is SylinthUI?

SylinthUI is a native dynamic library written in Rust. It creates a borderless, decoration-free window that renders a standard HTML/CSS/JS page using the system's built-in WebView engine โ€” WebView2 on Windows, WebKit on macOS, WebKitGTK on Linux.

Your application links against sylinthui.dll and calls a simple C API to create the window, register event handlers, and control it at runtime. No Electron, no Chromium bundled, no separate process โ€” just a DLL you drop next to your application.

๐ŸชŸ

Borderless Window

No title bar, no OS chrome. Window shape and drag behaviour fully controlled from CSS.

๐ŸŒ

Web Renderer

Full HTML5, CSS3, modern JS. Animations, canvas, WebGL โ€” if the browser supports it, SylinthUI does.

โšก

Native Bridge

JS fires events to C/C++ and C/C++ fires events back. Zero glue code needed.

๐ŸŽ›๏ธ

Runtime Control

Show, hide, reposition, resize, round corners, lock overlay โ€” all at runtime from any thread.

๐Ÿ”’

Memory Safe

Built in Rust. No memory leaks or dangling pointers are possible in the renderer layer.

๐Ÿ“ฆ

SDK-Style

Standard inc/ + lib/ + bin/ layout. Drop it in, link it, done.


โš™๏ธ How it works

SylinthUI runs as a single window inside your process. When you call sylinth_run() it spins up a tao event loop with a wry WebView embedded inside it on a dedicated internal OS thread, then returns immediately to the caller.

1

Create a handle

Call sylinth_create() or sylinth_create_percent(). No window appears yet.

2

Configure before launch

Call sylinth_set_initial_*() functions to set position, size, visibility, corners, always-on-top, resize lock, and focus lock.

3

Register event handlers

Call sylinth_on() to bind C callbacks to named events fired from JS or built-in events.

4

Run the window

Call sylinth_run(). The window appears, HTML loads, JS bridge is injected automatically. Blocks until closed.

5

Control at runtime

From any other thread call functions like sylinth_set_visible(), sylinth_set_always_on_top(), or sylinth_resize_percent(). Queued safely.

6

Clean up

Call sylinth_destroy() when you no longer need the window โ€” typically on application shutdown.


๐Ÿš€ Capabilities

A full overview of everything SylinthUI can do.

๐ŸชŸ

Borderless Window

Decoration-free window โ€” no title bar, no OS chrome. Shape, drag regions, and close button are entirely yours to design in HTML and CSS.

sylinth_create()
๐Ÿ‘๏ธ

Show / Hide

Window can be hidden and shown instantly without destroying it. WebView stays alive and loaded โ€” toggling has zero reload cost.

sylinth_set_visible()
๐Ÿ–ฑ๏ธ

Click-Through Mode

Window can be made fully transparent to mouse input. Clicks pass straight through โ€” perfect for HUD overlays that must be visible but non-blocking.

sylinth_set_interactive()
๐Ÿ“

Smart Positioning

Position at exact pixels or use "center", "start", "end" alignment strings that resolve against the current monitor at runtime.

sylinth_set_position_aligned()
๐Ÿ“

Percentage Sizing

Window size can be specified as a percentage of the primary monitor โ€” e.g. 70% ร— 75%. Resolves to correct pixels on any resolution from 1080p to 4K. Also resizable at runtime via percentage.

sylinth_create_percent()
๐Ÿ”ต

Rounded Corners

Native Windows 11 rounded corner support via DWM. Four styles: default, none, round, small. Degrades gracefully on older Windows.

sylinth_set_corners()
๐Ÿ“Œ

Always-on-Top

Forces the window above every other window via HWND_TOPMOST. Survives focus changes, new windows popping up, and alt-tab. Perfect for game overlays.

sylinth_set_always_on_top()
๐ŸŽฏ

Focus Lock

When active, the window reclaims focus the moment it is lost. Useful while a modal menu is open โ€” unlock it when the menu closes to return focus to the host application.

sylinth_set_focus_lock()
๐Ÿ”

Resize Lock

Prevents the user from resizing the window by dragging its edges. Locked by default โ€” borderless menus rarely need to be resizable. Can be toggled at runtime.

sylinth_set_resizable()
โšก

Bidirectional Events

JS calls Sylinth.emit() to send named events with JSON payloads to C++. C++ fires events back into JS at any time using the same system.

sylinth_on() / Sylinth.emit()
๐Ÿงต

Thread-Safe Runtime

All runtime control functions are safe to call from any thread. Commands are queued internally and applied on the next event loop tick.

Arc<Mutex<Vec<Cmd>>>
๐Ÿ”’

Memory Safe

Built entirely in Rust. The borrow checker enforces memory correctness at compile time โ€” no leaks, no dangling pointers, no use-after-free in the renderer layer.

Rust / zero UB
๐ŸŒ

Cross-Platform

Same Rust source on Windows (WebView2), macOS (WebKit), and Linux (WebKitGTK). Platform-specific features degrade gracefully on unsupported platforms.

Windows / macOS / Linux
๐Ÿ”Œ

C FFI Surface

Stable C ABI โ€” no C++ mangling, no templates. Any language that can call a C DLL can use SylinthUI: C++, C, Rust, Python, Go, and more.

extern "C"

๐Ÿ“ฆ Installation

SylinthUI ships as an SDK. Set up your project folder like this:

Directory Structure
YourProject/
โ”œโ”€โ”€ SylinthUI/
โ”‚   โ”œโ”€โ”€ inc/
โ”‚   โ”‚   โ””โ”€โ”€ sylinthui.h        โ† include this in your source
โ”‚   โ”œโ”€โ”€ lib/
โ”‚   โ”‚   โ””โ”€โ”€ sylinthui.dll.lib  โ† link against this
โ”‚   โ””โ”€โ”€ bin/
โ”‚       โ””โ”€โ”€ sylinthui.dll      โ† ship this next to your .exe / .asi
โ””โ”€โ”€ src/
    โ””โ”€โ”€ main.cpp

Visual Studio setup

1

C/C++ โ†’ Additional Include Directories

Add the path to SylinthUI/inc/

2

Linker โ†’ Additional Library Directories

Add the path to SylinthUI/lib/

3

Linker โ†’ Input โ†’ Additional Dependencies

Add sylinthui.dll.lib

4

Build Events โ†’ Post-Build Event

xcopy /Y "$(ProjectDir)SylinthUI\bin\sylinthui.dll" "$(OutDir)"

โ„น๏ธSylinthUI requires x64. Make sure your project configuration is set to x64.

๐ŸชŸ First Window

Two ways to create a window โ€” exact pixels or percentage of the monitor:

C++ โ€” Exact pixels
#include "sylinthui.h"

int main() {
    SylinthHandle* ui = sylinth_create(
        "My App", 1280, 720,
        "file:///C:/MyApp/ui/index.html", 0
    );
    sylinth_run(ui);    // returns immediately
    your_app_loop();    // your code runs here while window is open
    sylinth_destroy(ui); // call on shutdown
}
C++ โ€” Percentage of monitor
#include "sylinthui.h"

int main() {
    // 70% wide, 75% tall โ€” correct on any resolution
    SylinthHandle* ui = sylinth_create_percent(
        "My App", 70.0f, 75.0f,
        "file:///C:/MyApp/ui/index.html", 0
    );
    sylinth_run(ui);    // returns immediately
    your_app_loop();    // your code runs here while window is open
    sylinth_destroy(ui); // call on shutdown
}
โ„น๏ธThe URL can be a file:/// path, https:// URL, or data:text/html,... inline document.

๐ŸŒ HTML Page

SylinthUI automatically injects the Sylinth object before any of your scripts run. No import needed.

HTML
<style>
  body {
    -webkit-app-region: drag;    /* whole body is draggable */
    user-select: none;
  }
  button { -webkit-app-region: no-drag; } /* buttons opt out */
</style>

<script>
  Sylinth.on('sylinth:ready', () => console.log('Ready!'));

  function doSomething() {
    Sylinth.emit('buttonClicked', { value: 42 });
  }
</script>

๐Ÿ”„ Lifecycle API

FunctionDescription
sylinth_create(title, w, h, url, transparent)Create window at exact pixel size. Returns handle.
sylinth_create_percent(title, w%, h%, url, transparent)Create window at percentage of primary monitor (0.0โ€“100.0).
sylinth_run(handle)Open window and enter event loop. Blocks until closed.
sylinth_destroy(handle)Free all memory. Call after sylinth_run() returns.
sylinth_version()Returns version string as null-terminated C string.

๐Ÿ“ก Events

C++
void on_button_clicked(const char* name, const char* payload) {
    printf("Event: %s  Data: %s\n", name, payload);
}

sylinth_on(ui, "buttonClicked", on_button_clicked);
sylinth_off(ui, "buttonClicked");

Built-in events

EventWhenPayload
sylinth:readyWebView finished loading{}
sylinth:closeClose requested by OS or JS{}
sylinth:focusWindow gained or lost focus{"focused": true/false}

๐Ÿ”— JS Bridge

MethodDirectionDescription
Sylinth.emit(name, data)JS โ†’ C++Fire a named event with a JSON-serialisable payload.
Sylinth.on(name, fn)C++ โ†’ JSRegister a JS callback. Called when C++ fires sylinth_emit() into the page.
Sylinth.off(name)โ€”Remove all JS listeners for a named event.
JavaScript
Sylinth.emit('saveSettings', { volume: 0.8, fullscreen: true });

Sylinth.on('settingsSaved', (data) => {
    console.log('Confirmed:', data.success);
});

Sylinth.off('settingsSaved');

๐Ÿ“ค Emit to JS

Fire a named event with a JSON payload from your native code directly into the JS page. This is how C++ (or any language using the C ABI) pushes data to the UI โ€” updating health bars, spawning notifications, reflecting game state changes in real time.

Internally this uses evaluate_script() on the WebView and is safe to call from any thread โ€” it goes through the same command queue as all other runtime controls.

C++

C++
// Fire an event into the JS page from any thread
sylinth_emit(ui, "tornadoSpawned", "{\"intensity\":3,\"follow\":true}");
sylinth_emit(ui, "healthUpdated",  "{\"hp\":80,\"max\":100}");
sylinth_emit(ui, "menuClosed",     "{}"); // no payload โ€” pass {}

JS side

JavaScript
// Listen for events fired FROM C++
Sylinth.on('tornadoSpawned', (data) => {
    console.log('Intensity:', data.intensity, 'Follow:', data.follow);
    spawnTornadoVisual(data.intensity);
});

Sylinth.on('healthUpdated', (data) => {
    document.getElementById('hp-bar').style.width = (data.hp / data.max * 100) + '%';
    document.getElementById('hp-text').textContent = data.hp + '/' + data.max;
});

Sylinth.on('menuClosed', () => {
    document.getElementById('menu').classList.remove('visible');
});

C# (.NET wrapper)

C#
// Same thing from C#
SylinthUI.Emit(ui, "tornadoSpawned", "{\"intensity\":3}");
SylinthUI.Emit(ui, "menuClosed"); // payload defaults to {}
ParameterTypeDescription
handleSylinthHandle*The window handle returned by sylinth_create()
event_nameconst char*Name of the event โ€” must match what JS listens for with Sylinth.on()
payloadconst char*JSON string. Pass "{}" if there is no data to send.
โ„น๏ธsylinth_emit() is thread-safe. Call it from your game loop, a timer, an input handler โ€” any thread. The JS dispatch is queued and executed on the WebView's event loop tick.

๐ŸŽ›๏ธ Window Control

All runtime functions are thread-safe โ€” call from any thread while the window is running.

Visibility & Interactivity

C++
sylinth_set_visible(ui, 0);     // hide โ€” WebView stays alive
sylinth_set_visible(ui, 1);     // show again

sylinth_set_interactive(ui, 0); // click-through โ€” mouse passes to app behind
sylinth_set_interactive(ui, 1); // restore mouse interactivity

Initial state (before run)

C++
sylinth_set_initially_visible(ui, 0);
sylinth_set_initially_interactive(ui, 0);
sylinth_set_initially_resizable(ui, 0); // lock resize (default)
sylinth_run(ui);
โ„น๏ธCombining set_visible(1) with set_interactive(0) gives you a visible HUD overlay that does not block mouse input to the app behind it.

๐Ÿ“ Positioning

C++
// Alignment โ€” before run()
sylinth_set_initial_position_aligned(ui, "center", "center");
sylinth_set_initial_position_aligned(ui, "end",    "start");  // top-right
sylinth_set_initial_position_aligned(ui, "start",  "end");    // bottom-left

// Alignment โ€” runtime
sylinth_set_position_aligned(ui, "center", "center");

// Exact pixels
sylinth_set_initial_position(ui, 100, 200);
sylinth_set_position(ui, 100, 200);
ValueX axisY axis
"start"Left edgeTop edge
"center"Horizontally centeredVertically centered
"end"Right edgeBottom edge

๐Ÿ“ Sizing

SylinthUI supports two sizing modes โ€” exact pixels and a percentage of the current monitor. Percentage sizing resolves at the moment the window is created or resized, so it always produces the correct result regardless of the user's resolution.

Creating with a percentage

C++
// 70% wide, 75% tall โ€” 1344ร—810 on 1920ร—1080, 2240ร—1620 on 3200ร—2160
SylinthHandle* ui = sylinth_create_percent(
    "My App", 70.0f, 75.0f,
    "file:///C:/MyApp/ui/index.html", 0
);

Resizing at runtime

C++
// Resize to exact pixels
sylinth_resize(ui, 1280, 720);

// Resize to percentage of current monitor
sylinth_resize_percent(ui, 80.0f, 80.0f);

Resize lock

C++
// Prevent user from dragging window edges (default โ€” locked)
sylinth_set_initially_resizable(ui, 0);

// Allow resize at runtime if needed
sylinth_set_resizable(ui, 1);

// Lock it again
sylinth_set_resizable(ui, 0);

๐Ÿ”ต Corner Radius

Native Windows 11 rounded corners via DWM. Four styles available. Degrades silently on Windows 10 and earlier.

Default

"default"

None

"none"

Small

"small"

Round

"round"

C++
sylinth_set_initial_corners(ui, "round");  // before run()
sylinth_set_corners(ui, "small");          // at runtime
sylinth_set_corners(ui, "none");           // sharp corners
StyleDWM ValueDescription
"default"DWMWCP_DEFAULTOS decides โ€” typically rounded on Windows 11
"none"DWMWCP_DONOTROUNDSharp square corners
"round"DWMWCP_ROUNDLarge rounded corners (Windows 11 style)
"small"DWMWCP_ROUNDSMALLSubtle small rounded corners
โš ๏ธRequires Windows 11. Silently ignored on Windows 10 and earlier.

๐Ÿ“Œ Overlay & Focus

Always-on-top

Forces the window above every other window โ€” including fullscreen games. Uses HWND_TOPMOST internally, which survives new windows popping up, alt-tab previews, and focus changes.

C++
sylinth_set_initially_on_top(ui, 1);  // before run()
sylinth_set_always_on_top(ui, 1);     // at runtime โ€” pin above everything
sylinth_set_always_on_top(ui, 0);     // return to normal z-order

Focus lock

When active, the window immediately reclaims focus via SetForegroundWindow whenever it loses it. Designed to be used while a modal menu is open โ€” always unlock when the menu closes so the host application can regain focus naturally.

C++
bool g_open = false;

void toggle_menu() {
    g_open = !g_open;
    sylinth_set_visible    (ui, g_open ? 1 : 0);
    sylinth_set_interactive(ui, g_open ? 1 : 0);
    sylinth_set_focus_lock (ui, g_open ? 1 : 0); // lock while open, release when closed
}
โš ๏ธFocus lock prevents the user from switching to any other application while active. Always pair it with a way to close the menu โ€” either a button in your HTML or a key handler that calls sylinth_set_focus_lock(ui, 0).

Recommended overlay setup

For a game overlay like a GTA V mod menu โ€” always-on-top keeps the window above the game, click-through makes the HUD non-blocking, and focus lock is toggled only while the interactive menu is open:

C++
sylinth_set_initially_on_top(ui, 1);      // always above the game
sylinth_set_initially_visible(ui, 1);     // HUD visible from the start
sylinth_set_initially_interactive(ui, 0); // but click-through โ€” game has mouse

// On menu open (F5):
sylinth_set_interactive(ui, 1);  // take mouse
sylinth_set_focus_lock(ui, 1);   // lock focus to menu

// On menu close (F5 again or JS close button):
sylinth_set_interactive(ui, 0);  // return mouse to game
sylinth_set_focus_lock(ui, 0);   // return focus to game

๐Ÿ‘๏ธ Example โ€” Toggle Visibility

C++
SylinthHandle* g_ui   = nullptr;
bool           g_open  = false;

void toggle_menu() {
    g_open = !g_open;
    sylinth_set_visible    (g_ui, g_open ? 1 : 0);
    sylinth_set_interactive(g_ui, g_open ? 1 : 0);
    sylinth_set_focus_lock (g_ui, g_open ? 1 : 0);
}

int main() {
    g_ui = sylinth_create_percent(
        "My App", 70.0f, 75.0f,
        "file:///C:/MyApp/ui/index.html", 0
    );
    sylinth_set_initial_position_aligned(g_ui, "center", "center");
    sylinth_set_initial_corners(g_ui, "round");
    sylinth_set_initially_on_top(g_ui, 1);
    sylinth_set_initially_visible(g_ui, 0);
    sylinth_set_initially_interactive(g_ui, 0);
    sylinth_set_initially_resizable(g_ui, 0);

    // wire toggle_menu() to a key handler ...

    sylinth_run(g_ui);
    sylinth_destroy(g_ui);
}

๐Ÿ“ก Example โ€” Custom Events

C++
void on_save(const char* name, const char* payload) {
    // payload: {"volume":0.8,"username":"player1"}
    printf("Save: %s\n", payload);
}

sylinth_on(ui, "saveSettings", on_save);
JavaScript
function onSaveClicked() {
    Sylinth.emit('saveSettings', {
        volume: parseFloat(volumeSlider.value),
        username: usernameInput.value,
    });
}

Sylinth.on('saveConfirmed', (data) => {
    statusLabel.textContent = data.success ? 'Saved!' : 'Error';
});

๐Ÿ“‹ Full Example

A complete app โ€” percentage-sized, centered, rounded, always-on-top, resize locked, starts hidden, toggles with focus lock.

C++ โ€” main.cpp
#include "sylinthui.h"
#include <cstdio>

SylinthHandle* g_ui  = nullptr;
bool           g_open = false;

void on_ready(const char*, const char*) { printf("[App] Ready\n"); }

void on_close(const char*, const char*) {
    g_open = false;
    sylinth_set_visible(g_ui, 0);
    sylinth_set_interactive(g_ui, 0);
    sylinth_set_focus_lock(g_ui, 0);
}

void on_action(const char* name, const char* payload) {
    printf("[App] '%s': %s\n", name, payload);
}

void toggle_ui() {
    g_open = !g_open;
    sylinth_set_visible    (g_ui, g_open ? 1 : 0);
    sylinth_set_interactive(g_ui, g_open ? 1 : 0);
    sylinth_set_focus_lock (g_ui, g_open ? 1 : 0);
}

int main() {
    // 70% ร— 75% of screen โ€” works on any resolution
    g_ui = sylinth_create_percent(
        "My Application", 70.0f, 75.0f,
        "file:///C:/MyApp/ui/index.html", 0
    );

    sylinth_set_initial_position_aligned(g_ui, "center", "center");
    sylinth_set_initial_corners(g_ui, "round");
    sylinth_set_initially_on_top(g_ui, 1);
    sylinth_set_initially_visible(g_ui, 0);
    sylinth_set_initially_interactive(g_ui, 0);
    sylinth_set_initially_resizable(g_ui, 0);

    sylinth_on(g_ui, "sylinth:ready", on_ready);
    sylinth_on(g_ui, "sylinth:close", on_close);
    sylinth_on(g_ui, "doAction",      on_action);

    toggle_ui(); // open immediately for testing

    sylinth_run(g_ui); // returns immediately โ€” window runs on internal thread

    // Your application loop runs here while the window is open.
    // Call sylinth_destroy() on shutdown, not immediately after sylinth_run().
    your_app_loop();

    sylinth_destroy(g_ui); // call on shutdown
    return 0;
}
JavaScript โ€” index.html
Sylinth.on('sylinth:ready', () => {
    document.getElementById('status').textContent = 'Ready';
});

function triggerAction() {
    Sylinth.emit('doAction', { type: 'spawn', intensity: 3 });
}

function closeMenu() {
    Sylinth.emit('sylinth:close', {});
}
โš ๏ธBecause sylinth_run() blocks the calling thread, runtime controls like toggle_ui() must be called from a separate thread โ€” your game loop, a worker thread, or an input handler thread.