Files
cell/scripts/core/_sdl_video.js

221 lines
6.0 KiB
JavaScript

// SDL Video Actor
// This actor runs on the main thread and handles all SDL video operations
// Default window configuration - documents all available window options
var default_window = {
// Basic properties
title: "Prosperon Window",
width: 640,
height: 480,
// Position - can be numbers or "centered"
x: undefined, // SDL_WINDOWPOS_UNDEFINED by default
y: undefined, // SDL_WINDOWPOS_UNDEFINED by default
// Window behavior flags
resizable: true,
fullscreen: false,
hidden: false,
borderless: false,
alwaysOnTop: false,
minimized: false,
maximized: false,
// Input grabbing
mouseGrabbed: false,
keyboardGrabbed: false,
// Display properties
highPixelDensity: false,
transparent: false,
opacity: 1.0, // 0.0 to 1.0
// Focus behavior
notFocusable: false,
// Special window types (mutually exclusive)
utility: false, // Utility window (not in taskbar)
tooltip: false, // Tooltip window (requires parent)
popupMenu: false, // Popup menu window (requires parent)
// Graphics API flags (let SDL choose if not specified)
opengl: false, // Force OpenGL context
vulkan: false, // Force Vulkan context
metal: false, // Force Metal context (macOS)
// Advanced properties
parent: undefined, // Parent window for tooltips/popups/modal
modal: false, // Modal to parent window (requires parent)
externalGraphicsContext: false, // Use external graphics context
// Input handling
textInput: true, // Enable text input on creation
};
// Resource tracking
var resources = {
window: {},
renderer: {},
texture: {},
surface: {}
};
// ID counter for resource allocation
var next_id = 1;
// Helper to allocate new ID
function allocate_id() {
return next_id++;
}
// Message handler
$_.receiver(function(msg) {
if (!msg.kind || !msg.op) {
send(msg, {error: "Message must have 'kind' and 'op' fields"});
return;
}
var response = {};
try {
switch (msg.kind) {
case 'window':
response = handle_window(msg);
break;
case 'renderer':
response = handle_renderer(msg);
break;
case 'texture':
response = handle_texture(msg);
break;
default:
response = {error: "Unknown kind: " + msg.kind};
}
} catch (e) {
response = {error: e.toString()};
}
// Send response back
send(msg, response);
});
// Window operations
function handle_window(msg) {
switch (msg.op) {
case 'create':
var config = Object.assign({}, default_window, msg.data || {});
var id = allocate_id();
var window = new prosperon.endowments.window(config);
resources.window[id] = window;
return {id: id, data: {width: window.width, height: window.height}};
case 'destroy':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
resources.window[msg.id].destroy();
delete resources.window[msg.id];
return {success: true};
case 'show':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
resources.window[msg.id].show();
return {success: true};
case 'hide':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
resources.window[msg.id].hide();
return {success: true};
case 'set_title':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
if (!msg.data || !msg.data.title) {
return {error: "Missing title in data"};
}
resources.window[msg.id].title = msg.data.title;
return {success: true};
case 'get_size':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
var win = resources.window[msg.id];
return {data: {width: win.width, height: win.height}};
case 'set_size':
if (!msg.id || !resources.window[msg.id]) {
return {error: "Invalid window id: " + msg.id};
}
if (!msg.data || typeof msg.data.width !== 'number' || typeof msg.data.height !== 'number') {
return {error: "Missing or invalid width/height in data"};
}
var win = resources.window[msg.id];
win.width = msg.data.width;
win.height = msg.data.height;
return {success: true};
default:
return {error: "Unknown window operation: " + msg.op};
}
}
// Renderer operations
function handle_renderer(msg) {
switch (msg.op) {
case 'create':
if (!msg.data || !msg.data.window_id) {
return {error: "Missing window_id in data"};
}
if (!resources.window[msg.data.window_id]) {
return {error: "Invalid window id: " + msg.data.window_id};
}
var id = allocate_id();
var renderer = prosperon.endowments.renderer.create(resources.window[msg.data.window_id]);
resources.renderer[id] = renderer;
return {id: id};
case 'destroy':
if (!msg.id || !resources.renderer[msg.id]) {
return {error: "Invalid renderer id: " + msg.id};
}
resources.renderer[msg.id].destroy();
delete resources.renderer[msg.id];
return {success: true};
case 'clear':
if (!msg.id || !resources.renderer[msg.id]) {
return {error: "Invalid renderer id: " + msg.id};
}
resources.renderer[msg.id].clear();
return {success: true};
case 'present':
if (!msg.id || !resources.renderer[msg.id]) {
return {error: "Invalid renderer id: " + msg.id};
}
resources.renderer[msg.id].present();
return {success: true};
default:
return {error: "Unknown renderer operation: " + msg.op};
}
}
// Texture operations
function handle_texture(msg) {
switch (msg.op) {
case 'create':
// TODO: Implement texture creation
return {error: "Texture operations not yet implemented"};
default:
return {error: "Unknown texture operation: " + msg.op};
}
}