Files
cell-sdl3/tray.c
2025-12-11 10:39:24 -06:00

256 lines
7.1 KiB
C

#include "cell.h"
#include <SDL3/SDL.h>
// Forward declaration for surface function
extern SDL_Surface *js2SDL_Surface(JSContext *js, JSValue val);
// SDL_Tray class
void SDL_Tray_free(JSRuntime *rt, SDL_Tray *tray) {
if (tray) SDL_DestroyTray(tray);
}
QJSCLASS(SDL_Tray,)
// SDL_TrayMenu class (not freed separately - destroyed with tray)
void SDL_TrayMenu_free(JSRuntime *rt, SDL_TrayMenu *menu) {
// Menus are destroyed with their parent tray
}
QJSCLASS(SDL_TrayMenu,)
// SDL_TrayEntry class (not freed separately - destroyed with tray)
void SDL_TrayEntry_free(JSRuntime *rt, SDL_TrayEntry *entry) {
// Entries are destroyed with their parent tray
}
QJSCLASS(SDL_TrayEntry,)
// SDL_CreateTray(icon, tooltip) -> Tray object
JSC_CCALL(tray_create,
SDL_Surface *icon = NULL;
const char *tooltip = NULL;
if (argc > 0 && !JS_IsNull(argv[0])) {
icon = js2SDL_Surface(js, argv[0]);
}
if (argc > 1 && !JS_IsNull(argv[1])) {
tooltip = JS_ToCString(js, argv[1]);
}
SDL_Tray *tray = SDL_CreateTray(icon, tooltip);
if (tooltip) JS_FreeCString(js, tooltip);
if (!tray) return JS_NULL;
return SDL_Tray2js(js, tray);
)
// Tray instance methods
JSC_CCALL(tray_set_icon,
SDL_Tray *tray = js2SDL_Tray(js, self);
SDL_Surface *icon = NULL;
if (argc > 0 && !JS_IsNull(argv[0])) {
icon = js2SDL_Surface(js, argv[0]);
}
SDL_SetTrayIcon(tray, icon);
return JS_NULL;
)
JSC_CCALL(tray_set_tooltip,
SDL_Tray *tray = js2SDL_Tray(js, self);
const char *tooltip = NULL;
if (argc > 0 && !JS_IsNull(argv[0])) {
tooltip = JS_ToCString(js, argv[0]);
}
SDL_SetTrayTooltip(tray, tooltip);
if (tooltip) JS_FreeCString(js, tooltip);
return JS_NULL;
)
JSC_CCALL(tray_create_menu,
SDL_Tray *tray = js2SDL_Tray(js, self);
SDL_TrayMenu *menu = SDL_CreateTrayMenu(tray);
if (!menu) return JS_NULL;
return SDL_TrayMenu2js(js, menu);
)
JSC_CCALL(tray_get_menu,
SDL_Tray *tray = js2SDL_Tray(js, self);
SDL_TrayMenu *menu = SDL_GetTrayMenu(tray);
if (!menu) return JS_NULL;
return SDL_TrayMenu2js(js, menu);
)
JSC_CCALL(tray_destroy,
SDL_Tray *tray = js2SDL_Tray(js, self);
SDL_DestroyTray(tray);
return JS_NULL;
)
// TrayMenu instance methods
JSC_CCALL(traymenu_get_entries,
SDL_TrayMenu *menu = js2SDL_TrayMenu(js, self);
int count = 0;
const SDL_TrayEntry **entries = SDL_GetTrayEntries(menu, &count);
if (!entries) return JS_NewArray(js);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < count; i++) {
JS_SetPropertyUint32(js, arr, i, SDL_TrayEntry2js(js, (SDL_TrayEntry*)entries[i]));
}
return arr;
)
JSC_CCALL(traymenu_insert_entry,
SDL_TrayMenu *menu = js2SDL_TrayMenu(js, self);
int pos = -1;
const char *label = NULL;
uint32_t flags = SDL_TRAYENTRY_BUTTON;
if (argc > 0) JS_ToInt32(js, &pos, argv[0]);
if (argc > 1 && !JS_IsNull(argv[1])) {
label = JS_ToCString(js, argv[1]);
}
if (argc > 2) JS_ToUint32(js, &flags, argv[2]);
SDL_TrayEntry *entry = SDL_InsertTrayEntryAt(menu, pos, label, flags);
if (label) JS_FreeCString(js, label);
if (!entry) return JS_NULL;
return SDL_TrayEntry2js(js, entry);
)
JSC_CCALL(traymenu_get_parent_tray,
SDL_TrayMenu *menu = js2SDL_TrayMenu(js, self);
SDL_Tray *tray = SDL_GetTrayMenuParentTray(menu);
if (!tray) return JS_NULL;
return SDL_Tray2js(js, tray);
)
JSC_CCALL(traymenu_get_parent_entry,
SDL_TrayMenu *menu = js2SDL_TrayMenu(js, self);
SDL_TrayEntry *entry = SDL_GetTrayMenuParentEntry(menu);
if (!entry) return JS_NULL;
return SDL_TrayEntry2js(js, entry);
)
// TrayEntry instance methods
JSC_CCALL(trayentry_create_submenu,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
SDL_TrayMenu *menu = SDL_CreateTraySubmenu(entry);
if (!menu) return JS_NULL;
return SDL_TrayMenu2js(js, menu);
)
JSC_CCALL(trayentry_get_submenu,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
SDL_TrayMenu *menu = SDL_GetTraySubmenu(entry);
if (!menu) return JS_NULL;
return SDL_TrayMenu2js(js, menu);
)
JSC_CCALL(trayentry_set_label,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
const char *label = JS_ToCString(js, argv[0]);
if (!label) return JS_EXCEPTION;
SDL_SetTrayEntryLabel(entry, label);
JS_FreeCString(js, label);
return JS_NULL;
)
JSC_CCALL(trayentry_get_label,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
const char *label = SDL_GetTrayEntryLabel(entry);
return label ? JS_NewString(js, label) : JS_NULL;
)
JSC_CCALL(trayentry_set_checked,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
bool checked = JS_ToBool(js, argv[0]);
SDL_SetTrayEntryChecked(entry, checked);
return JS_NULL;
)
JSC_CCALL(trayentry_get_checked,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
return JS_NewBool(js, SDL_GetTrayEntryChecked(entry));
)
JSC_CCALL(trayentry_set_enabled,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
bool enabled = JS_ToBool(js, argv[0]);
SDL_SetTrayEntryEnabled(entry, enabled);
return JS_NULL;
)
JSC_CCALL(trayentry_get_enabled,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
return JS_NewBool(js, SDL_GetTrayEntryEnabled(entry));
)
JSC_CCALL(trayentry_get_parent,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
SDL_TrayMenu *menu = SDL_GetTrayEntryParent(entry);
if (!menu) return JS_NULL;
return SDL_TrayMenu2js(js, menu);
)
JSC_CCALL(trayentry_remove,
SDL_TrayEntry *entry = js2SDL_TrayEntry(js, self);
SDL_RemoveTrayEntry(entry);
return JS_NULL;
)
static const JSCFunctionListEntry js_SDL_Tray_funcs[] = {
MIST_FUNC_DEF(tray, set_icon, 1),
MIST_FUNC_DEF(tray, set_tooltip, 1),
MIST_FUNC_DEF(tray, create_menu, 0),
MIST_FUNC_DEF(tray, get_menu, 0),
MIST_FUNC_DEF(tray, destroy, 0),
};
static const JSCFunctionListEntry js_SDL_TrayMenu_funcs[] = {
MIST_FUNC_DEF(traymenu, get_entries, 0),
MIST_FUNC_DEF(traymenu, insert_entry, 3),
MIST_FUNC_DEF(traymenu, get_parent_tray, 0),
MIST_FUNC_DEF(traymenu, get_parent_entry, 0),
};
static const JSCFunctionListEntry js_SDL_TrayEntry_funcs[] = {
MIST_FUNC_DEF(trayentry, create_submenu, 0),
MIST_FUNC_DEF(trayentry, get_submenu, 0),
MIST_FUNC_DEF(trayentry, set_label, 1),
MIST_FUNC_DEF(trayentry, get_label, 0),
MIST_FUNC_DEF(trayentry, set_checked, 1),
MIST_FUNC_DEF(trayentry, get_checked, 0),
MIST_FUNC_DEF(trayentry, set_enabled, 1),
MIST_FUNC_DEF(trayentry, get_enabled, 0),
MIST_FUNC_DEF(trayentry, get_parent, 0),
MIST_FUNC_DEF(trayentry, remove, 0),
};
static const JSCFunctionListEntry js_tray_funcs[] = {
MIST_FUNC_DEF(tray, create, 2),
};
SDL_Surface *js2SDL_Surface(JSContext *js, JSValue val);
CELL_USE_INIT(
QJSCLASSPREP_FUNCS(SDL_Tray);
QJSCLASSPREP_FUNCS(SDL_TrayMenu);
QJSCLASSPREP_FUNCS(SDL_TrayEntry);
JSValue ret = JS_NewObject(js);
JS_SetPropertyFunctionList(js, ret, js_tray_funcs, countof(js_tray_funcs));
// Export entry flags
JS_SetPropertyStr(js, ret, "BUTTON", JS_NewUint32(js, SDL_TRAYENTRY_BUTTON));
JS_SetPropertyStr(js, ret, "CHECKBOX", JS_NewUint32(js, SDL_TRAYENTRY_CHECKBOX));
JS_SetPropertyStr(js, ret, "SUBMENU", JS_NewUint32(js, SDL_TRAYENTRY_SUBMENU));
JS_SetPropertyStr(js, ret, "DISABLED", JS_NewUint32(js, SDL_TRAYENTRY_DISABLED));
JS_SetPropertyStr(js, ret, "CHECKED", JS_NewUint32(js, SDL_TRAYENTRY_CHECKED));
return ret;
)