@owear/linux-x64-gnu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,112 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ #pragma once
4
+ //
5
+ // ow/Window.h — ventanas multiplataforma con titlebar custom/overlay.
6
+ // Contrato compartido: window_win.cpp / window_mac.mm / window_linux.cpp
7
+ //
8
+
9
+ #include "ow/Common.h"
10
+
11
+ namespace ow {
12
+
13
+ enum class TitleBarStyle {
14
+ Default, // decoraciones del sistema tal cual
15
+ Hidden, // sin titlebar; la ventana completa es contenido (frameless)
16
+ Custom // titlebar custom + botones nativos overlay (donde el SO lo permite)
17
+ };
18
+
19
+ struct TitleBarOverlay {
20
+ bool enabled = false;
21
+ std::string color = "#00000000"; // fondo bajo los botones nativos
22
+ std::string symbolColor = "#ffffff"; // color de glifos (min/max/close)
23
+ int height = 36; // alto en px lógicos
24
+ };
25
+
26
+ struct WindowOptions {
27
+ std::string title = "Owear";
28
+ int width = 1024;
29
+ int height = 768;
30
+ int minWidth = 0, minHeight = 0;
31
+ int maxWidth = 0, maxHeight = 0;
32
+ bool resizable = true;
33
+ bool center = true;
34
+ bool show = true;
35
+ bool frameless = false;
36
+
37
+ TitleBarStyle titleBarStyle = TitleBarStyle::Default;
38
+ TitleBarOverlay titleBarOverlay;
39
+
40
+ /// URL inicial: http(s):// (dev server), app://<bundle>/... o file://
41
+ std::string url = "app://index.html";
42
+
43
+ /// Argumentos extra para el proceso del WebView (debug flags, etc).
44
+ std::vector<std::string> webviewArgs;
45
+ };
46
+
47
+ /// Payload de evento como JSON serializado ("null" si el evento no lleva datos).
48
+ using EventPayload = std::string_view;
49
+ using ListenerId = uint64_t;
50
+
51
+ class Window : NonCopyable {
52
+ public:
53
+ explicit Window(const WindowOptions& options);
54
+ ~Window();
55
+
56
+ WindowId Id() const;
57
+
58
+ // ── ciclo de vida ──────────────────────────────────────────────
59
+ void Show();
60
+ void Hide();
61
+ void Close(); // dispara closeRequested; puede ser vetado por listeners
62
+ void Destroy(); // cierre inmediato sin veto
63
+ void Focus();
64
+
65
+ // ── estado ─────────────────────────────────────────────────────
66
+ void Minimize();
67
+ void Maximize();
68
+ void Unmaximize();
69
+ void Restore();
70
+ void SetFullScreen(bool enabled);
71
+ bool IsMaximized() const;
72
+ bool IsMinimized() const;
73
+ bool IsFullScreen() const;
74
+
75
+ // ── geometría ──────────────────────────────────────────────────
76
+ struct Bounds { int x = 0, y = 0, w = 0, h = 0; };
77
+ Bounds GetBounds() const;
78
+ void SetBounds(const Bounds&);
79
+ void Center();
80
+
81
+ // ── apariencia / titlebar ───────────────────────────────────────
82
+ void SetTitle(const std::string& title);
83
+ std::string Title() const;
84
+ void SetTitleBarStyle(TitleBarStyle style);
85
+ void SetTitleBarOverlay(const TitleBarOverlay& overlay);
86
+
87
+ // ── webview ────────────────────────────────────────────────────
88
+ void LoadURL(const std::string& url);
89
+ /// Evalúa JS en la página. callback recibe el resultado JSON o null.
90
+ void EvalJS(const std::string& js,
91
+ std::function<void(std::string_view resultJson)> callback = nullptr);
92
+
93
+ // ── eventos hacia JS (bridge) y C++ ─────────────────────────────
94
+ /// Emite un evento a todos los suscriptores JS de esta ventana.
95
+ void EmitToJS(const std::string& name, std::string_view jsonPayload);
96
+ /// Suscriptor nativo. Los eventos nativos se reenvían a JS automáticamente.
97
+ ListenerId On(const std::string& name, std::function<void(EventPayload)> cb);
98
+ void Off(ListenerId id);
99
+
100
+ /// Referencia cruda al backend de plataforma (solo para src/ interno).
101
+ void* NativeHandle() const;
102
+
103
+ /// Detrás de este puntero vive el estado de plataforma.
104
+ class Impl; // definido en src/Window/Window_p.hpp
105
+ std::unique_ptr<Impl> impl_;
106
+
107
+ public:
108
+ /// Interno (ControlServer): respuesta del SDK al closeRequested.
109
+ class Impl* impl() { return impl_.get(); }
110
+ };
111
+
112
+ } // namespace ow
@@ -0,0 +1,419 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // ow/detail/minjson.hpp — JSON minimalista, header-only, sin excepciones.
5
+ // Usado por el kernel (bridge/control) y disponible para módulos vía ow/Json.h.
6
+ //
7
+ // Diseño: Value inmutable tras parse; objetos preservan orden de inserción.
8
+ //
9
+
10
+ #pragma once
11
+
12
+ #include <cstdint>
13
+ #include <cmath>
14
+ #include <string>
15
+ #include <string_view>
16
+ #include <vector>
17
+ #include <utility>
18
+ #include <optional>
19
+
20
+ namespace ow::json {
21
+
22
+ class Value;
23
+ using Array = std::vector<Value>;
24
+ using Member = std::pair<std::string, Value>;
25
+ using Object = std::vector<Member>;
26
+
27
+ enum class Type : uint8_t { Null, Bool, Int, Double, String, ArrayT, ObjectT };
28
+
29
+ class Value {
30
+ public:
31
+ Value() : type_(Type::Null) {}
32
+ Value(std::nullptr_t) : type_(Type::Null) {}
33
+ Value(bool b) : type_(Type::Bool), bool_(b) {}
34
+ Value(int v) : type_(Type::Int), int_(v) {}
35
+ Value(int64_t v) : type_(Type::Int), int_(v) {}
36
+ Value(uint32_t v) : type_(Type::Int), int_(v) {}
37
+ Value(double v) : type_(IsIntegral(v) ? Type::Int : Type::Double),
38
+ int_(static_cast<int64_t>(v)) {}
39
+ Value(const char* s) : type_(Type::String), str_(s) {}
40
+ Value(std::string s) : type_(Type::String), str_(std::move(s)) {}
41
+ Value(Array a) : type_(Type::ArrayT), arr_(std::move(a)) {}
42
+ Value(Object o) : type_(Type::ObjectT), obj_(std::move(o)) {}
43
+
44
+ Type GetType() const { return type_; }
45
+ bool IsNull() const { return type_ == Type::Null; }
46
+ bool IsBool() const { return type_ == Type::Bool; }
47
+ bool IsNumber() const { return type_ == Type::Int || type_ == Type::Double; }
48
+ bool IsString() const { return type_ == Type::String; }
49
+ bool IsArray() const { return type_ == Type::ArrayT; }
50
+ bool IsObject() const { return type_ == Type::ObjectT; }
51
+
52
+ bool AsBool(bool def = false) const { return IsBool() ? bool_ : def; }
53
+ int64_t AsInt(int64_t def = 0) const {
54
+ if (type_ == Type::Int) return int_;
55
+ if (type_ == Type::Double) return static_cast<int64_t>(dbl_);
56
+ return def;
57
+ }
58
+ double AsDouble(double def = 0) const {
59
+ if (type_ == Type::Double) return dbl_;
60
+ if (type_ == Type::Int) return static_cast<double>(int_);
61
+ return def;
62
+ }
63
+ const std::string& AsString() const { return str_; }
64
+
65
+ const Array& AsArray() const { return arr_; }
66
+ const Object& AsObject() const { return obj_; }
67
+
68
+ /// Acceso a miembro de objeto. nullptr si no existe o no es objeto.
69
+ const Value* Find(std::string_view key) const {
70
+ if (type_ != Type::ObjectT) return nullptr;
71
+ for (const auto& m : obj_)
72
+ if (m.first == key) return &m.second;
73
+ return nullptr;
74
+ }
75
+
76
+ std::string Serialize() const {
77
+ std::string out;
78
+ out.reserve(64);
79
+ Write(out);
80
+ return out;
81
+ }
82
+
83
+ private:
84
+ static bool IsIntegral(double v) {
85
+ return std::isfinite(v) && v >= -9.007199254740992e15 && v <= 9.007199254740992e15
86
+ && v == static_cast<double>(static_cast<int64_t>(v));
87
+ }
88
+
89
+ void Write(std::string& out) const {
90
+ switch (type_) {
91
+ case Type::Null: out += "null"; break;
92
+ case Type::Bool: out += bool_ ? "true" : "false"; break;
93
+ case Type::Int: {
94
+ char tmp[24];
95
+ int n = std::snprintf(tmp, sizeof(tmp), "%lld",
96
+ static_cast<long long>(int_));
97
+ out.append(tmp, static_cast<size_t>(n));
98
+ break;
99
+ }
100
+ case Type::Double: {
101
+ char tmp[36];
102
+ int n = std::snprintf(tmp, sizeof(tmp), "%.17g", dbl_);
103
+ // recorta precisión redundante con %g corto cuando es exacto
104
+ char tmp2[36];
105
+ int n2 = std::snprintf(tmp2, sizeof(tmp2), "%.15g", dbl_);
106
+ if (n > 0 && n2 > 0 && std::strtod(tmp2, nullptr) == dbl_)
107
+ out.append(tmp2, static_cast<size_t>(n2));
108
+ else
109
+ out.append(tmp, static_cast<size_t>(n));
110
+ break;
111
+ }
112
+ case Type::String:
113
+ WriteEscaped(out, str_);
114
+ break;
115
+ case Type::ArrayT: {
116
+ out += '[';
117
+ bool first = true;
118
+ for (const auto& v : arr_) {
119
+ if (!first) out += ',';
120
+ first = false;
121
+ v.Write(out);
122
+ }
123
+ out += ']';
124
+ break;
125
+ }
126
+ case Type::ObjectT: {
127
+ out += '{';
128
+ bool first = true;
129
+ for (const auto& m : obj_) {
130
+ if (!first) out += ',';
131
+ first = false;
132
+ WriteEscaped(out, m.first);
133
+ out += ':';
134
+ m.second.Write(out);
135
+ }
136
+ out += '}';
137
+ break;
138
+ }
139
+ }
140
+ }
141
+
142
+ static void WriteEscaped(std::string& out, std::string_view s) {
143
+ out += '"';
144
+ for (unsigned char c : s) {
145
+ switch (c) {
146
+ case '"': out += "\\\""; break;
147
+ case '\\': out += "\\\\"; break;
148
+ case '\b': out += "\\b"; break;
149
+ case '\f': out += "\\f"; break;
150
+ case '\n': out += "\\n"; break;
151
+ case '\r': out += "\\r"; break;
152
+ case '\t': out += "\\t"; break;
153
+ default:
154
+ if (c < 0x20) {
155
+ char tmp[8];
156
+ std::snprintf(tmp, sizeof(tmp), "\\u%04x", c);
157
+ out += tmp;
158
+ } else {
159
+ out += static_cast<char>(c);
160
+ }
161
+ }
162
+ }
163
+ out += '"';
164
+ }
165
+
166
+ Type type_;
167
+ bool bool_ = false;
168
+ int64_t int_ = 0;
169
+ double dbl_ = 0;
170
+ std::string str_;
171
+ Array arr_;
172
+ Object obj_;
173
+ };
174
+
175
+ /// Parser recursivo descendente. Devuelve nullopt y `error` en fallo.
176
+ struct ParseResult {
177
+ std::optional<Value> value;
178
+ std::string error;
179
+ };
180
+
181
+ inline ParseResult Parse(std::string_view text) {
182
+ size_t pos = 0;
183
+ ParseResult r;
184
+
185
+ // Límite de anidamiento (objetos/arrays): evita stack overflow con JSON
186
+ // adversarial profundamente anidado en entradas externas (bridge/control).
187
+ static constexpr int kMaxDepth = 128;
188
+
189
+ struct Parser {
190
+ std::string_view t;
191
+ size_t& pos;
192
+ std::string err;
193
+ int depth = 0;
194
+
195
+ void SkipWs() {
196
+ while (pos < t.size()) {
197
+ char c = t[pos];
198
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r') ++pos;
199
+ else break;
200
+ }
201
+ }
202
+ bool Fail(std::string msg) { if (err.empty()) err = std::move(msg); return false; }
203
+
204
+ bool ParseValue(Value& out) {
205
+ SkipWs();
206
+ if (pos >= t.size()) return Fail("fin inesperado");
207
+ char c = t[pos];
208
+ switch (c) {
209
+ case '{': return ParseObject(out);
210
+ case '[': return ParseArray(out);
211
+ case '"': {
212
+ std::string s;
213
+ if (!ParseString(s)) return false;
214
+ out = Value(std::move(s));
215
+ return true;
216
+ }
217
+ case 't':
218
+ return Literal("true") ? (out = Value(true), true) : false;
219
+ case 'f':
220
+ return Literal("false") ? (out = Value(false), true) : false;
221
+ case 'n':
222
+ return Literal("null") ? (out = Value(nullptr), true) : false;
223
+ default:
224
+ return ParseNumber(out);
225
+ }
226
+ }
227
+
228
+ bool Literal(std::string_view lit) {
229
+ if (t.compare(pos, lit.size(), lit) != 0)
230
+ return Fail("literal inválido");
231
+ pos += lit.size();
232
+ return true;
233
+ }
234
+
235
+ bool ParseNumber(Value& out) {
236
+ size_t start = pos;
237
+ bool isDouble = false;
238
+ if (pos < t.size() && (t[pos] == '-' || t[pos] == '+')) ++pos;
239
+ while (pos < t.size()) {
240
+ char c = t[pos];
241
+ if (c >= '0' && c <= '9') { ++pos; continue; }
242
+ if (c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-') {
243
+ if (c == '.' || c == 'e' || c == 'E') isDouble = true;
244
+ ++pos; continue;
245
+ }
246
+ break;
247
+ }
248
+ if (pos == start) return Fail("número inválido");
249
+ std::string num(t.substr(start, pos - start));
250
+ if (isDouble) {
251
+ out = Value(std::strtod(num.c_str(), nullptr));
252
+ } else {
253
+ errno = 0;
254
+ long long v = std::strtoll(num.c_str(), nullptr, 10);
255
+ out = Value(static_cast<int64_t>(v));
256
+ }
257
+ return true;
258
+ }
259
+
260
+ bool ParseHex4(unsigned& out) {
261
+ if (pos + 4 > t.size()) return Fail("\\u truncado");
262
+ unsigned v = 0;
263
+ for (int i = 0; i < 4; ++i) {
264
+ char c = t[pos++];
265
+ v <<= 4;
266
+ if (c >= '0' && c <= '9') v |= static_cast<unsigned>(c - '0');
267
+ else if (c >= 'a' && c <= 'f') v |= static_cast<unsigned>(c - 'a' + 10);
268
+ else if (c >= 'A' && c <= 'F') v |= static_cast<unsigned>(c - 'A' + 10);
269
+ else return Fail("\\u inválido");
270
+ }
271
+ out = v;
272
+ return true;
273
+ }
274
+
275
+ void AppendUtf8(std::string& s, unsigned cp) {
276
+ if (cp < 0x80) {
277
+ s += static_cast<char>(cp);
278
+ } else if (cp < 0x800) {
279
+ s += static_cast<char>(0xC0 | (cp >> 6));
280
+ s += static_cast<char>(0x80 | (cp & 0x3F));
281
+ } else if (cp < 0x10000) {
282
+ s += static_cast<char>(0xE0 | (cp >> 12));
283
+ s += static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
284
+ s += static_cast<char>(0x80 | (cp & 0x3F));
285
+ } else {
286
+ s += static_cast<char>(0xF0 | (cp >> 18));
287
+ s += static_cast<char>(0x80 | ((cp >> 12) & 0x3F));
288
+ s += static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
289
+ s += static_cast<char>(0x80 | (cp & 0x3F));
290
+ }
291
+ }
292
+
293
+ bool ParseString(std::string& out) {
294
+ ++pos; // comilla inicial ya validada por caller
295
+ out.clear();
296
+ while (pos < t.size()) {
297
+ char c = t[pos++];
298
+ if (c == '"') return true;
299
+ if (c != '\\') { out += c; continue; }
300
+ if (pos >= t.size()) return Fail("escape truncado");
301
+ char e = t[pos++];
302
+ switch (e) {
303
+ case '"': out += '"'; break;
304
+ case '\\': out += '\\'; break;
305
+ case '/': out += '/'; break;
306
+ case 'b': out += '\b'; break;
307
+ case 'f': out += '\f'; break;
308
+ case 'n': out += '\n'; break;
309
+ case 'r': out += '\r'; break;
310
+ case 't': out += '\t'; break;
311
+ case 'u': {
312
+ unsigned u;
313
+ if (!ParseHex4(u)) return false;
314
+ if (u >= 0xD800 && u <= 0xDBFF &&
315
+ pos + 1 < t.size() && t[pos] == '\\' && t[pos + 1] == 'u') {
316
+ pos += 2;
317
+ unsigned lo;
318
+ if (!ParseHex4(lo)) return false;
319
+ if (lo >= 0xDC00 && lo <= 0xDFFF)
320
+ u = 0x10000 + ((u - 0xD800) << 10) + (lo - 0xDC00);
321
+ else
322
+ AppendUtf8(out, u), u = lo; // par inválido: emite ambos
323
+ }
324
+ AppendUtf8(out, u);
325
+ break;
326
+ }
327
+ default: return Fail("escape desconocido");
328
+ }
329
+ }
330
+ return Fail("string sin cerrar");
331
+ }
332
+
333
+ bool ParseArray(Value& out) {
334
+ if (++depth > kMaxDepth) return Fail("JSON demasiado anidado");
335
+ ++pos;
336
+ Array arr;
337
+ SkipWs();
338
+ if (pos < t.size() && t[pos] == ']') { ++pos; --depth; out = Value(std::move(arr)); return true; }
339
+ while (true) {
340
+ Value item;
341
+ if (!ParseValue(item)) return false;
342
+ arr.push_back(std::move(item));
343
+ SkipWs();
344
+ if (pos >= t.size()) return Fail("array sin cerrar");
345
+ if (t[pos] == ',') { ++pos; continue; }
346
+ if (t[pos] == ']') { ++pos; break; }
347
+ return Fail("',' o ']' esperado");
348
+ }
349
+ --depth;
350
+ out = Value(std::move(arr));
351
+ return true;
352
+ }
353
+
354
+ bool ParseObject(Value& out) {
355
+ if (++depth > kMaxDepth) return Fail("JSON demasiado anidado");
356
+ ++pos;
357
+ Object obj;
358
+ SkipWs();
359
+ if (pos < t.size() && t[pos] == '}') { ++pos; --depth; out = Value(std::move(obj)); return true; }
360
+ while (true) {
361
+ SkipWs();
362
+ if (pos >= t.size() || t[pos] != '"')
363
+ return Fail("clave string esperada");
364
+ std::string key;
365
+ if (!ParseString(key)) return false;
366
+ SkipWs();
367
+ if (pos >= t.size() || t[pos] != ':')
368
+ return Fail("':' esperado");
369
+ ++pos;
370
+ Value val;
371
+ if (!ParseValue(val)) return false;
372
+ obj.emplace_back(std::move(key), std::move(val));
373
+ SkipWs();
374
+ if (pos >= t.size()) return Fail("objeto sin cerrar");
375
+ if (t[pos] == ',') { ++pos; continue; }
376
+ if (t[pos] == '}') { ++pos; break; }
377
+ return Fail("',' o '}' esperado");
378
+ }
379
+ --depth;
380
+ out = Value(std::move(obj));
381
+ return true;
382
+ }
383
+ };
384
+
385
+ Parser p{text, pos};
386
+ Value root;
387
+ if (!p.ParseValue(root)) {
388
+ r.error = p.err.empty() ? "JSON inválido" : p.err;
389
+ return r;
390
+ }
391
+ r.value = std::move(root);
392
+ return r;
393
+ }
394
+
395
+ /// Escape de un string para incrustarlo como literal JS entre comillas simples.
396
+ /// Se usa para inyectar payloads vía evaluate_javascript/postMessage roundtrips.
397
+ inline std::string JsLiteral(std::string_view s) {
398
+ std::string out = "'";
399
+ for (char c : s) {
400
+ switch (c) {
401
+ case '\'': out += "\\'"; break;
402
+ case '\\': out += "\\\\"; break;
403
+ case '\n': out += "\\n"; break;
404
+ case '\r': out += "\\r"; break;
405
+ default:
406
+ if (static_cast<unsigned char>(c) < 0x20) {
407
+ char tmp[8];
408
+ std::snprintf(tmp, sizeof(tmp), "\\u%04x", c);
409
+ out += tmp;
410
+ } else {
411
+ out += c;
412
+ }
413
+ }
414
+ }
415
+ out += '\'';
416
+ return out;
417
+ }
418
+
419
+ } // namespace ow::json
@@ -0,0 +1,103 @@
1
+ // Copyright 2026 Owear Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //
4
+ // api/ow_api.h — ABI-C estable del sistema de módulos Owear (.owm).
5
+ //
6
+ // Cada API vive en su propio folder (api/fs, api/process, …) y compila a una
7
+ // shared library independiente (.so/.dll/.dylib) que el kernel carga con
8
+ // dlopen. Actualización modular por API.
9
+ //
10
+ // Un módulo exporta EXACTAMENTE un símbolo obligatorio:
11
+ // const ow_module_desc_t* ow_module_descriptor(void);
12
+ // y opcionalmente recibe el host con:
13
+ // void ow_module_set_host(const ow_module_host_t* host);
14
+ //
15
+ // Contrato de memoria:
16
+ // - Los buffers apuntados por res viven SOLO durante la llamada; el host
17
+ // copia inmediatamente después de retornar.
18
+ // - Prohibido lanzar excepciones hacia el host.
19
+ //
20
+ #pragma once
21
+
22
+ #include <stdint.h>
23
+ #include <stddef.h>
24
+
25
+ #if defined(_WIN32)
26
+ #if defined(OW_MODULE_BUILD)
27
+ #define OW_MODULE_EXPORT __declspec(dllexport)
28
+ #else
29
+ #define OW_MODULE_EXPORT
30
+ #endif
31
+ #else
32
+ #if defined(OW_MODULE_BUILD)
33
+ #define OW_MODULE_EXPORT __attribute__((visibility("default")))
34
+ #else
35
+ #define OW_MODULE_EXPORT
36
+ #endif
37
+ #endif
38
+
39
+ #ifdef __cplusplus
40
+ extern "C" {
41
+ #endif
42
+
43
+ typedef struct ow_request {
44
+ const char* json; ///< argumentos como array JSON. Nunca null ("[]").
45
+ uint32_t json_len;
46
+ const uint8_t* bin; ///< binario adjunto (puede ser null)
47
+ uint32_t bin_len;
48
+ uint32_t window_id; ///< ventana invocante (0 = sin ventana)
49
+ uint32_t reserved;
50
+ void* host; ///< contexto del kernel (opaco para el módulo)
51
+ } ow_request_t;
52
+
53
+ typedef struct ow_response {
54
+ int32_t status; ///< 0 = ok; != 0 = error
55
+ const char* error; ///< mensaje de error (si status != 0)
56
+ const char* json; ///< resultado JSON ("null" permitido)
57
+ uint32_t json_len;
58
+ const uint8_t* bin; ///< binario de salida (opcional)
59
+ uint32_t bin_len;
60
+ } ow_response_t;
61
+
62
+ typedef void (*ow_fn_t)(const ow_request_t* req, ow_response_t* res);
63
+
64
+ typedef struct ow_fn_entry {
65
+ const char* name;
66
+ ow_fn_t fn;
67
+ } ow_fn_entry_t;
68
+
69
+ typedef struct ow_module_desc {
70
+ const char* name; ///< "fs", "process", "dialog", …
71
+ const char* version;
72
+ const ow_fn_entry_t* fns;
73
+ uint32_t fn_count;
74
+ } ow_module_desc_t;
75
+
76
+ /// Único símbolo que un .owm debe exportar.
77
+ typedef const ow_module_desc_t* (*ow_module_entry_t)(void);
78
+
79
+ // ── Host callbacks (F-infra) ────────────────────────────────────────────────
80
+ // El kernel pasa esta tabla vía ow_module_set_host() justo después del dlopen.
81
+ // Permite a los módulos emitir eventos (watchers, PTY stdout, tray clicks…).
82
+
83
+ #define OW_HOST_ABI_VERSION 1
84
+
85
+ typedef void (*ow_host_emit_event_t)(void* ctx, uint32_t window_id,
86
+ const char* name, const char* json);
87
+ typedef void (*ow_host_log_t)(void* ctx, int level, const char* msg);
88
+
89
+ typedef struct ow_module_host {
90
+ uint32_t version; ///< OW_HOST_ABI_VERSION
91
+ void* ctx; ///< contexto opaco del kernel
92
+ ow_host_emit_event_t emit_event;
93
+ ///< window_id == 0 → broadcast (todas las ventanas + SDK por control socket)
94
+ ow_host_log_t log; ///< level: 0 debug · 1 info · 2 warn · 3 error
95
+ void* reserved[4];
96
+ } ow_module_host_t;
97
+
98
+ /// Opcional: el módulo guarda la tabla si quiere emitir eventos.
99
+ typedef void (*ow_module_set_host_t)(const ow_module_host_t* host);
100
+
101
+ #ifdef __cplusplus
102
+ } // extern "C"
103
+ #endif
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@owear/linux-x64-gnu",
3
+ "version": "0.1.0",
4
+ "description": "Owear runtime — kernel nativo + módulos stock (.owm) + headers. Linux x64 (glibc).",
5
+ "license": "Apache-2.0",
6
+ "homepage": "https://owear.dev",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/owear/owear.git",
10
+ "directory": "packages/runtime-linux-x64-gnu"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "os": ["linux"],
16
+ "cpu": ["x64"],
17
+ "libc": ["glibc"],
18
+ "engines": { "node": ">=20" },
19
+ "bin": { "owear": "bin/owear" },
20
+ "files": ["bin", "include", "README.md", "LICENSE"],
21
+ "scripts": {
22
+ "prepack": "node ../../tools/pack-runtime.mjs --target linux-x64-gnu"
23
+ }
24
+ }