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.
Create a handle
Call sylinth_create() or sylinth_create_percent(). No window appears yet.
Configure before launch
Call sylinth_set_initial_*() functions to set position, size, visibility, corners, always-on-top, resize lock, and focus lock.
Register event handlers
Call sylinth_on() to bind C callbacks to named events fired from JS or built-in events.
Run the window
Call sylinth_run(). The window appears, HTML loads, JS bridge is injected automatically. Blocks until closed.
Control at runtime
From any other thread call functions like sylinth_set_visible(), sylinth_set_always_on_top(), or sylinth_resize_percent(). Queued safely.
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 UBCross-Platform
Same Rust source on Windows (WebView2), macOS (WebKit), and Linux (WebKitGTK). Platform-specific features degrade gracefully on unsupported platforms.
Windows / macOS / LinuxC 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:
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
C/C++ โ Additional Include Directories
Add the path to SylinthUI/inc/
Linker โ Additional Library Directories
Add the path to SylinthUI/lib/
Linker โ Input โ Additional Dependencies
Add sylinthui.dll.lib
Build Events โ Post-Build Event
xcopy /Y "$(ProjectDir)SylinthUI\bin\sylinthui.dll" "$(OutDir)"
First Window
Two ways to create a window โ exact pixels or percentage of the monitor:
#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 }
#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 }
HTML Page
SylinthUI automatically injects the Sylinth object before any of your scripts run. No import needed.
<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
| Function | Description |
|---|---|
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
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
| Event | When | Payload |
|---|---|---|
sylinth:ready | WebView finished loading | {} |
sylinth:close | Close requested by OS or JS | {} |
sylinth:focus | Window gained or lost focus | {"focused": true/false} |
JS Bridge
| Method | Direction | Description |
|---|---|---|
Sylinth.emit(name, data) | JS โ C++ | Fire a named event with a JSON-serialisable payload. |
Sylinth.on(name, fn) | C++ โ JS | Register a JS callback. Called when C++ fires sylinth_emit() into the page. |
Sylinth.off(name) | โ | Remove all JS listeners for a named event. |
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++
// 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
// 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)
// Same thing from C# SylinthUI.Emit(ui, "tornadoSpawned", "{\"intensity\":3}"); SylinthUI.Emit(ui, "menuClosed"); // payload defaults to {}
| Parameter | Type | Description |
|---|---|---|
handle | SylinthHandle* | The window handle returned by sylinth_create() |
event_name | const char* | Name of the event โ must match what JS listens for with Sylinth.on() |
payload | const char* | JSON string. Pass "{}" if there is no data to send. |
Window Control
All runtime functions are thread-safe โ call from any thread while the window is running.
Visibility & Interactivity
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)
sylinth_set_initially_visible(ui, 0); sylinth_set_initially_interactive(ui, 0); sylinth_set_initially_resizable(ui, 0); // lock resize (default) sylinth_run(ui);
Positioning
// 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);
| Value | X axis | Y axis |
|---|---|---|
"start" | Left edge | Top edge |
"center" | Horizontally centered | Vertically centered |
"end" | Right edge | Bottom 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
// 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
// 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
// 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"
sylinth_set_initial_corners(ui, "round"); // before run() sylinth_set_corners(ui, "small"); // at runtime sylinth_set_corners(ui, "none"); // sharp corners
| Style | DWM Value | Description |
|---|---|---|
"default" | DWMWCP_DEFAULT | OS decides โ typically rounded on Windows 11 |
"none" | DWMWCP_DONOTROUND | Sharp square corners |
"round" | DWMWCP_ROUND | Large rounded corners (Windows 11 style) |
"small" | DWMWCP_ROUNDSMALL | Subtle small rounded corners |
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.
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.
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 }
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:
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
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
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);
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.
#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; }
Sylinth.on('sylinth:ready', () => { document.getElementById('status').textContent = 'Ready'; }); function triggerAction() { Sylinth.emit('doAction', { type: 'spawn', intensity: 3 }); } function closeMenu() { Sylinth.emit('sylinth:close', {}); }