nomen-lang 0.11.0 → 0.12.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.
- package/NOMEN_AGENTS.md +7 -6
- package/core/System/Controls/App.nm +8 -0
- package/core/System/Controls/Container.nm +148 -44
- package/core/System/Controls/Window.nm +363 -51
- package/core/assets/nomen.png +0 -0
- package/dist/index.mjs +3030 -404
- package/package.json +1 -1
- package/src/args.ts +1 -1
- package/src/index.ts +15 -1
- package/src/types/Config.ts +1 -1
|
@@ -19,6 +19,14 @@ pub mv struct Window: Control {
|
|
|
19
19
|
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
20
20
|
((void(*)(id, SEL, long))objc_msgSend)(app, sel_registerName("setActivationPolicy:"), 0);
|
|
21
21
|
((void(*)(id, SEL, BOOL))objc_msgSend)(app, sel_registerName("activateIgnoringOtherApps:"), 1);
|
|
22
|
+
// Install AppKit's default Apple Event handlers (Dock Quit and the
|
|
23
|
+
// rest): without finishLaunching there is no handler for the quit
|
|
24
|
+
// event, so Dock Quit is silently ignored (-1708). Once per process.
|
|
25
|
+
static BOOL nomen_finished_launching = 0;
|
|
26
|
+
if (!nomen_finished_launching) {
|
|
27
|
+
((void(*)(id, SEL))objc_msgSend)(app, sel_registerName("finishLaunching"));
|
|
28
|
+
nomen_finished_launching = 1;
|
|
29
|
+
}
|
|
22
30
|
// Create window
|
|
23
31
|
unsigned long style = 1 | 2 | 4 | 8;
|
|
24
32
|
id win = ((id(*)(id, SEL, double, double, double, double, unsigned long, unsigned long, BOOL))objc_msgSend)(
|
|
@@ -33,6 +41,10 @@ pub mv struct Window: Control {
|
|
|
33
41
|
((void(*)(id, SEL, double, double))objc_msgSend)(
|
|
34
42
|
win, sel_registerName("setFrameTopLeftPoint:"), 100.0, 100.0);
|
|
35
43
|
((void(*)(id, SEL, id))objc_msgSend)(win, sel_registerName("makeKeyAndOrderFront:"), (id)0);
|
|
44
|
+
// Survive close: on macOS the app outlives its last window and a
|
|
45
|
+
// Dock click reopens it, so a closed window's handle must stay
|
|
46
|
+
// valid (the default releases the NSWindow on close).
|
|
47
|
+
((void(*)(id, SEL, BOOL))objc_msgSend)(win, sel_registerName("setReleasedWhenClosed:"), 0);
|
|
36
48
|
// The content view must resize with the window and autoresize its
|
|
37
49
|
// subviews so each control's autoresizingMask takes effect during a
|
|
38
50
|
// live resize (AppKit's blocking drag loop bypasses our event loop).
|
|
@@ -48,6 +60,15 @@ pub mv struct Window: Control {
|
|
|
48
60
|
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
49
61
|
((void(*)(id, SEL, long))objc_msgSend)(app, sel_registerName("setActivationPolicy:"), 0);
|
|
50
62
|
((void(*)(id, SEL, BOOL))objc_msgSend)(app, sel_registerName("activateIgnoringOtherApps:"), 1);
|
|
63
|
+
// Install AppKit's default Apple Event handlers (Dock Quit and the
|
|
64
|
+
// rest): without finishLaunching there is no handler for the quit
|
|
65
|
+
// event, so Dock Quit is silently ignored (-1708). Once per process.
|
|
66
|
+
static BOOL nomen_finished_launching = 0;
|
|
67
|
+
if (!nomen_finished_launching) {
|
|
68
|
+
((void(*)(id, SEL))objc_msgSend)(app, sel_registerName("finishLaunching"));
|
|
69
|
+
nomen_finished_launching = 1;
|
|
70
|
+
}
|
|
71
|
+
((void(*)(id, SEL))objc_msgSend)(app, sel_registerName("finishLaunching"));
|
|
51
72
|
// Create window
|
|
52
73
|
unsigned long style = 1 | 2 | 4 | 8;
|
|
53
74
|
id win = ((id(*)(id, SEL, double, double, double, double, unsigned long, unsigned long, BOOL))objc_msgSend)(
|
|
@@ -62,6 +83,10 @@ pub mv struct Window: Control {
|
|
|
62
83
|
((void(*)(id, SEL, double, double))objc_msgSend)(
|
|
63
84
|
win, sel_registerName("setFrameTopLeftPoint:"), 100.0, 100.0);
|
|
64
85
|
((void(*)(id, SEL, id))objc_msgSend)(win, sel_registerName("makeKeyAndOrderFront:"), (id)0);
|
|
86
|
+
// Survive close: on macOS the app outlives its last window and a
|
|
87
|
+
// Dock click reopens it, so a closed window's handle must stay
|
|
88
|
+
// valid (the default releases the NSWindow on close).
|
|
89
|
+
((void(*)(id, SEL, BOOL))objc_msgSend)(win, sel_registerName("setReleasedWhenClosed:"), 0);
|
|
65
90
|
// The content view must resize with the window and autoresize its
|
|
66
91
|
// subviews so each control's autoresizingMask takes effect during a
|
|
67
92
|
// live resize (AppKit's blocking drag loop bypasses our event loop).
|
|
@@ -1078,6 +1103,140 @@ pub mv struct Window: Control {
|
|
|
1078
1103
|
```
|
|
1079
1104
|
}
|
|
1080
1105
|
|
|
1106
|
+
// ── App lifetime ─────────────────────────────────────────────────────
|
|
1107
|
+
// The macOS convention: closing the last window does NOT end the
|
|
1108
|
+
// process — the app stays alive (Dock icon, app menu) until the user
|
|
1109
|
+
// quits it (dock Quit; ⌘Q once an app menu exists). `run` keeps
|
|
1110
|
+
// pumping after the last window closes via `keep_alive`; the process
|
|
1111
|
+
// exits when macOS delivers a Quit, or when the app calls `quit()`.
|
|
1112
|
+
|
|
1113
|
+
// True when the app has been asked to quit (Window.quit()).
|
|
1114
|
+
pub func quit_requested = (self, out bool) {
|
|
1115
|
+
```
|
|
1116
|
+
#arch: c
|
|
1117
|
+
#platform: macos
|
|
1118
|
+
extern int nomen_app_quit;
|
|
1119
|
+
return nomen_app_quit != 0;
|
|
1120
|
+
```
|
|
1121
|
+
```
|
|
1122
|
+
#arch: aarch64_use_c
|
|
1123
|
+
#platform: macos
|
|
1124
|
+
extern int nomen_app_quit;
|
|
1125
|
+
return nomen_app_quit != 0;
|
|
1126
|
+
```
|
|
1127
|
+
```
|
|
1128
|
+
#arch: c
|
|
1129
|
+
#platform: ios
|
|
1130
|
+
return 0;
|
|
1131
|
+
```
|
|
1132
|
+
```
|
|
1133
|
+
#arch: aarch64_use_c
|
|
1134
|
+
#platform: ios
|
|
1135
|
+
return 0;
|
|
1136
|
+
```
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// The default Dock icon: the Nomen logo (core/assets/nomen.png, a
|
|
1140
|
+
// full-bleed square rasterized from the SVG by the site's icon script)
|
|
1141
|
+
// — embedded at library build time and laid out by set_icon. `run`
|
|
1142
|
+
// applies it at startup; call this directly in manual-loop apps that
|
|
1143
|
+
// don't go through run.
|
|
1144
|
+
pub func apply_default_icon = () {
|
|
1145
|
+
Window.set_icon(#embed_file("assets/nomen.png"))
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// Quit the APP (not just the window): sets the app-quit flag and closes
|
|
1149
|
+
// this window. `run`/`keep_alive` return once the flag is set, so main
|
|
1150
|
+
// unwinds normally. This is the programmatic equivalent of the Dock's
|
|
1151
|
+
// Quit — distinct from `close()`, which closes one window and leaves
|
|
1152
|
+
// the process alive.
|
|
1153
|
+
pub func quit = (self) {
|
|
1154
|
+
self.set_quit_flag()
|
|
1155
|
+
self.close()
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Sets the app-quit flag (raw-only body: aarch64 replaces the whole
|
|
1159
|
+
// body with its raw blocks).
|
|
1160
|
+
func set_quit_flag = (self) {
|
|
1161
|
+
```
|
|
1162
|
+
#arch: c
|
|
1163
|
+
#platform: macos
|
|
1164
|
+
extern int nomen_app_quit;
|
|
1165
|
+
nomen_app_quit = 1;
|
|
1166
|
+
```
|
|
1167
|
+
```
|
|
1168
|
+
#arch: aarch64_use_c
|
|
1169
|
+
#platform: macos
|
|
1170
|
+
extern int nomen_app_quit;
|
|
1171
|
+
nomen_app_quit = 1;
|
|
1172
|
+
```
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// Pump events until the app quits. Called by `run` after the last
|
|
1176
|
+
// window closes (macOS keeps the process alive), and available to
|
|
1177
|
+
// manual-loop apps that want the same lifetime: after your
|
|
1178
|
+
// `while win.is_visible()` ends, the app is still open in the
|
|
1179
|
+
// platform's eyes — hand control to the pump so Dock Quit and other
|
|
1180
|
+
// system interactions keep working.
|
|
1181
|
+
pub func keep_alive = () {
|
|
1182
|
+
while !Window.quit_flag() {
|
|
1183
|
+
Window.process_events()
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// True when the Dock was clicked while every window was closed —
|
|
1188
|
+
// Window.run resumes the frame loop for the reopened window.
|
|
1189
|
+
pub func reopen_flag = (out bool) {
|
|
1190
|
+
```
|
|
1191
|
+
#arch: c
|
|
1192
|
+
#platform: macos
|
|
1193
|
+
extern int nomen_app_reopen;
|
|
1194
|
+
return nomen_app_reopen != 0;
|
|
1195
|
+
```
|
|
1196
|
+
```
|
|
1197
|
+
#arch: aarch64_use_c
|
|
1198
|
+
#platform: macos
|
|
1199
|
+
extern int nomen_app_reopen;
|
|
1200
|
+
return nomen_app_reopen != 0;
|
|
1201
|
+
```
|
|
1202
|
+
```
|
|
1203
|
+
#arch: c
|
|
1204
|
+
#platform: ios
|
|
1205
|
+
return 0;
|
|
1206
|
+
```
|
|
1207
|
+
```
|
|
1208
|
+
#arch: aarch64_use_c
|
|
1209
|
+
#platform: ios
|
|
1210
|
+
return 0;
|
|
1211
|
+
```
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// The raw app-quit flag behind `quit_requested`/`keep_alive`.
|
|
1215
|
+
func quit_flag = (out bool) {
|
|
1216
|
+
```
|
|
1217
|
+
#arch: c
|
|
1218
|
+
#platform: macos
|
|
1219
|
+
extern int nomen_app_quit;
|
|
1220
|
+
return nomen_app_quit != 0;
|
|
1221
|
+
```
|
|
1222
|
+
```
|
|
1223
|
+
#arch: aarch64_use_c
|
|
1224
|
+
#platform: macos
|
|
1225
|
+
extern int nomen_app_quit;
|
|
1226
|
+
return nomen_app_quit != 0;
|
|
1227
|
+
```
|
|
1228
|
+
```
|
|
1229
|
+
#arch: c
|
|
1230
|
+
#platform: ios
|
|
1231
|
+
return 0;
|
|
1232
|
+
```
|
|
1233
|
+
```
|
|
1234
|
+
#arch: aarch64_use_c
|
|
1235
|
+
#platform: ios
|
|
1236
|
+
return 0;
|
|
1237
|
+
```
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1081
1240
|
// Returns the width of the window's content view.
|
|
1082
1241
|
pub func content_width = (self, out int) {
|
|
1083
1242
|
```
|
|
@@ -1313,6 +1472,136 @@ pub mv struct Window: Control {
|
|
|
1313
1472
|
// disarmed right after. Left armed it is process-global — every LATER
|
|
1314
1473
|
// red-button close (another window, a later run loop) would silently
|
|
1315
1474
|
// bypass App.close_requested forever.
|
|
1475
|
+
// Replace the Dock icon with the app's own art (PNG bytes — usually an
|
|
1476
|
+
// `#embed_file` literal). AppKit draws a runtime icon image as-is (Tahoe
|
|
1477
|
+
// only masks its outer bounds), so full-bleed art renders edge-to-edge
|
|
1478
|
+
// and looks oversized beside native icons. Normalise onto Apple's
|
|
1479
|
+
// app-icon grid first: aspect-fit the art into an 824px squircle body
|
|
1480
|
+
// centred on a transparent 1024px canvas. Any square source works; pass
|
|
1481
|
+
// raw complete art, not a pre-masked icon. App-wide on macOS: every
|
|
1482
|
+
// window shares the single Dock tile, so this is static for call-site
|
|
1483
|
+
// ergonomics (`Window.set_icon(png)`).
|
|
1484
|
+
pub func set_icon = (string png) {
|
|
1485
|
+
```
|
|
1486
|
+
#arch: c
|
|
1487
|
+
#platform: macos
|
|
1488
|
+
#include <math.h>
|
|
1489
|
+
id data = ((id(*)(id, SEL, const void*, unsigned long))objc_msgSend)(
|
|
1490
|
+
(id)objc_getClass("NSData"), sel_registerName("dataWithBytes:length:"),
|
|
1491
|
+
(const void *)png.ptr, (unsigned long)png.len);
|
|
1492
|
+
id source = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSImage"), sel_registerName("alloc"));
|
|
1493
|
+
source = ((id(*)(id, SEL, id))objc_msgSend)(source, sel_registerName("initWithData:"), data);
|
|
1494
|
+
if (!source) return;
|
|
1495
|
+
|
|
1496
|
+
const double canvas = 1024.0;
|
|
1497
|
+
const double body = 824.0;
|
|
1498
|
+
const double inset = (canvas - body) / 2.0;
|
|
1499
|
+
id image = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSImage"), sel_registerName("alloc"));
|
|
1500
|
+
image = ((id(*)(id, SEL, NSSize))objc_msgSend)(image, sel_registerName("initWithSize:"), NSMakeSize(canvas, canvas));
|
|
1501
|
+
((void(*)(id, SEL))objc_msgSend)(image, sel_registerName("lockFocus"));
|
|
1502
|
+
((void(*)(id, SEL))objc_msgSend)(
|
|
1503
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSColor"), sel_registerName("clearColor")),
|
|
1504
|
+
sel_registerName("set"));
|
|
1505
|
+
NSRectFill(NSMakeRect(0.0, 0.0, canvas, canvas));
|
|
1506
|
+
|
|
1507
|
+
// Squircle: a superellipse (n = 5) matching Apple's continuous
|
|
1508
|
+
// corners, fitted to the 824px body.
|
|
1509
|
+
id clip = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSBezierPath"), sel_registerName("bezierPath"));
|
|
1510
|
+
for (int step = 0; step < 240; step++) {
|
|
1511
|
+
const double angle = ((double)step / 240.0) * 6.283185307179586;
|
|
1512
|
+
const double cos_angle = cos(angle);
|
|
1513
|
+
const double sin_angle = sin(angle);
|
|
1514
|
+
const double x = canvas / 2.0 + (body / 2.0) * (cos_angle < 0.0 ? -pow(-cos_angle, 0.4) : pow(cos_angle, 0.4));
|
|
1515
|
+
const double y = canvas / 2.0 + (body / 2.0) * (sin_angle < 0.0 ? -pow(-sin_angle, 0.4) : pow(sin_angle, 0.4));
|
|
1516
|
+
if (step == 0) {
|
|
1517
|
+
((void(*)(id, SEL, NSPoint))objc_msgSend)(clip, sel_registerName("moveToPoint:"), NSMakePoint(x, y));
|
|
1518
|
+
} else {
|
|
1519
|
+
((void(*)(id, SEL, NSPoint))objc_msgSend)(clip, sel_registerName("lineToPoint:"), NSMakePoint(x, y));
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
((void(*)(id, SEL))objc_msgSend)(clip, sel_registerName("closePath"));
|
|
1523
|
+
((void(*)(id, SEL))objc_msgSend)(clip, sel_registerName("addClip"));
|
|
1524
|
+
|
|
1525
|
+
// Aspect-fit the source art inside the body (square icons fill it).
|
|
1526
|
+
const NSSize source_size = ((NSSize(*)(id, SEL))objc_msgSend)(source, sel_registerName("size"));
|
|
1527
|
+
const double longest = source_size.width > source_size.height ? source_size.width : source_size.height;
|
|
1528
|
+
const double scale = longest > 0.0 ? body / longest : 1.0;
|
|
1529
|
+
const double width = source_size.width * scale;
|
|
1530
|
+
const double height = source_size.height * scale;
|
|
1531
|
+
((void(*)(id, SEL, NSRect))objc_msgSend)(
|
|
1532
|
+
source, sel_registerName("drawInRect:"),
|
|
1533
|
+
NSMakeRect(inset + (body - width) / 2.0, inset + (body - height) / 2.0, width, height));
|
|
1534
|
+
((void(*)(id, SEL))objc_msgSend)(image, sel_registerName("unlockFocus"));
|
|
1535
|
+
|
|
1536
|
+
id nsapp = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
1537
|
+
((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setApplicationIconImage:"), image);
|
|
1538
|
+
```
|
|
1539
|
+
```
|
|
1540
|
+
#arch: aarch64_use_c
|
|
1541
|
+
#platform: macos
|
|
1542
|
+
#include <math.h>
|
|
1543
|
+
id data = ((id(*)(id, SEL, const void*, unsigned long))objc_msgSend)(
|
|
1544
|
+
(id)objc_getClass("NSData"), sel_registerName("dataWithBytes:length:"),
|
|
1545
|
+
(const void *)png.ptr, (unsigned long)png.len);
|
|
1546
|
+
id source = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSImage"), sel_registerName("alloc"));
|
|
1547
|
+
source = ((id(*)(id, SEL, id))objc_msgSend)(source, sel_registerName("initWithData:"), data);
|
|
1548
|
+
if (!source) return;
|
|
1549
|
+
|
|
1550
|
+
const double canvas = 1024.0;
|
|
1551
|
+
const double body = 824.0;
|
|
1552
|
+
const double inset = (canvas - body) / 2.0;
|
|
1553
|
+
id image = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSImage"), sel_registerName("alloc"));
|
|
1554
|
+
image = ((id(*)(id, SEL, NSSize))objc_msgSend)(image, sel_registerName("initWithSize:"), NSMakeSize(canvas, canvas));
|
|
1555
|
+
((void(*)(id, SEL))objc_msgSend)(image, sel_registerName("lockFocus"));
|
|
1556
|
+
((void(*)(id, SEL))objc_msgSend)(
|
|
1557
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSColor"), sel_registerName("clearColor")),
|
|
1558
|
+
sel_registerName("set"));
|
|
1559
|
+
NSRectFill(NSMakeRect(0.0, 0.0, canvas, canvas));
|
|
1560
|
+
|
|
1561
|
+
// Squircle: a superellipse (n = 5) matching Apple's continuous
|
|
1562
|
+
// corners, fitted to the 824px body.
|
|
1563
|
+
id clip = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSBezierPath"), sel_registerName("bezierPath"));
|
|
1564
|
+
for (int step = 0; step < 240; step++) {
|
|
1565
|
+
const double angle = ((double)step / 240.0) * 6.283185307179586;
|
|
1566
|
+
const double cos_angle = cos(angle);
|
|
1567
|
+
const double sin_angle = sin(angle);
|
|
1568
|
+
const double x = canvas / 2.0 + (body / 2.0) * (cos_angle < 0.0 ? -pow(-cos_angle, 0.4) : pow(cos_angle, 0.4));
|
|
1569
|
+
const double y = canvas / 2.0 + (body / 2.0) * (sin_angle < 0.0 ? -pow(-sin_angle, 0.4) : pow(sin_angle, 0.4));
|
|
1570
|
+
if (step == 0) {
|
|
1571
|
+
((void(*)(id, SEL, NSPoint))objc_msgSend)(clip, sel_registerName("moveToPoint:"), NSMakePoint(x, y));
|
|
1572
|
+
} else {
|
|
1573
|
+
((void(*)(id, SEL, NSPoint))objc_msgSend)(clip, sel_registerName("lineToPoint:"), NSMakePoint(x, y));
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
((void(*)(id, SEL))objc_msgSend)(clip, sel_registerName("closePath"));
|
|
1577
|
+
((void(*)(id, SEL))objc_msgSend)(clip, sel_registerName("addClip"));
|
|
1578
|
+
|
|
1579
|
+
// Aspect-fit the source art inside the body (square icons fill it).
|
|
1580
|
+
const NSSize source_size = ((NSSize(*)(id, SEL))objc_msgSend)(source, sel_registerName("size"));
|
|
1581
|
+
const double longest = source_size.width > source_size.height ? source_size.width : source_size.height;
|
|
1582
|
+
const double scale = longest > 0.0 ? body / longest : 1.0;
|
|
1583
|
+
const double width = source_size.width * scale;
|
|
1584
|
+
const double height = source_size.height * scale;
|
|
1585
|
+
((void(*)(id, SEL, NSRect))objc_msgSend)(
|
|
1586
|
+
source, sel_registerName("drawInRect:"),
|
|
1587
|
+
NSMakeRect(inset + (body - width) / 2.0, inset + (body - height) / 2.0, width, height));
|
|
1588
|
+
((void(*)(id, SEL))objc_msgSend)(image, sel_registerName("unlockFocus"));
|
|
1589
|
+
|
|
1590
|
+
id nsapp = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
1591
|
+
((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setApplicationIconImage:"), image);
|
|
1592
|
+
```
|
|
1593
|
+
```
|
|
1594
|
+
#arch: c
|
|
1595
|
+
#platform: ios
|
|
1596
|
+
/* TODO: iOS */
|
|
1597
|
+
```
|
|
1598
|
+
```
|
|
1599
|
+
#arch: aarch64_use_c
|
|
1600
|
+
#platform: ios
|
|
1601
|
+
/* TODO: iOS */
|
|
1602
|
+
```
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1316
1605
|
pub func close = (self) {
|
|
1317
1606
|
```
|
|
1318
1607
|
#arch: c
|
|
@@ -1357,68 +1646,91 @@ pub mv struct Window: Control {
|
|
|
1357
1646
|
app.start(ref self)
|
|
1358
1647
|
Container.arm_resize_delegate(self)
|
|
1359
1648
|
self.arm_mouse_moves()
|
|
1649
|
+
Window.apply_default_icon()
|
|
1360
1650
|
self.relayout(0)
|
|
1361
1651
|
self.show()
|
|
1362
1652
|
self.relayout(1)
|
|
1363
1653
|
var int prev_w = self.content_width()
|
|
1364
1654
|
var int prev_h = self.content_height()
|
|
1365
1655
|
var ev = FrameEvents()
|
|
1366
|
-
while
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
if app.close_requested(ref self) {
|
|
1656
|
+
while true {
|
|
1657
|
+
while self.is_visible() {
|
|
1658
|
+
// App menu Quit / ⌘Q (or quit()): close the window — the
|
|
1659
|
+
// quit flag then ends the app below.
|
|
1660
|
+
if self.quit_flag() {
|
|
1372
1661
|
self.close()
|
|
1373
1662
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
ev.click_y = self.click_y()
|
|
1383
|
-
ev.mouse_button = self.mouse_button()
|
|
1384
|
-
ev.mouse_click_count = self.mouse_click_count()
|
|
1385
|
-
ev.mouse_modifiers = self.mouse_modifiers()
|
|
1386
|
-
ev.scroll_dx = self.scroll_dx()
|
|
1387
|
-
ev.scroll_dy = self.scroll_dy()
|
|
1388
|
-
ev.key_code = self.key_code()
|
|
1389
|
-
ev.key_modifiers = self.key_modifiers()
|
|
1390
|
-
ev.key_repeat = self.key_repeat()
|
|
1391
|
-
ev.key_up_code = self.key_up_code()
|
|
1392
|
-
ev.mouse_x = self.mouse_x()
|
|
1393
|
-
ev.mouse_y = self.mouse_y()
|
|
1394
|
-
ev.dt = self.dt()
|
|
1395
|
-
ev.resized = false
|
|
1396
|
-
self.stamp_resize(false, 0, 0)
|
|
1397
|
-
var int cur_w = self.content_width()
|
|
1398
|
-
var int cur_h = self.content_height()
|
|
1399
|
-
if cur_w != prev_w {
|
|
1400
|
-
ev.resized = true
|
|
1663
|
+
// Close interception: the delegate refused the native close and
|
|
1664
|
+
// set the pending flag; consult the app. Accept → forced close
|
|
1665
|
+
// (bypasses the delegate); decline → window stays, flag cleared.
|
|
1666
|
+
if self.close_pending() {
|
|
1667
|
+
if app.close_requested(ref self) {
|
|
1668
|
+
self.close()
|
|
1669
|
+
}
|
|
1670
|
+
self.clear_close_pending()
|
|
1401
1671
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1672
|
+
// An accepted close above releases the native window mid-frame;
|
|
1673
|
+
// skip the rest of this iteration (the while re-checks and
|
|
1674
|
+
// exits).
|
|
1675
|
+
if self.is_visible() {
|
|
1676
|
+
ev.click = Window.process_events()
|
|
1677
|
+
ev.click_x = self.click_x()
|
|
1678
|
+
ev.click_y = self.click_y()
|
|
1679
|
+
ev.mouse_button = self.mouse_button()
|
|
1680
|
+
ev.mouse_click_count = self.mouse_click_count()
|
|
1681
|
+
ev.mouse_modifiers = self.mouse_modifiers()
|
|
1682
|
+
ev.scroll_dx = self.scroll_dx()
|
|
1683
|
+
ev.scroll_dy = self.scroll_dy()
|
|
1684
|
+
ev.key_code = self.key_code()
|
|
1685
|
+
ev.key_modifiers = self.key_modifiers()
|
|
1686
|
+
ev.key_repeat = self.key_repeat()
|
|
1687
|
+
ev.key_up_code = self.key_up_code()
|
|
1688
|
+
ev.mouse_x = self.mouse_x()
|
|
1689
|
+
ev.mouse_y = self.mouse_y()
|
|
1690
|
+
ev.dt = self.dt()
|
|
1691
|
+
ev.resized = false
|
|
1692
|
+
self.stamp_resize(false, 0, 0)
|
|
1693
|
+
var int cur_w = self.content_width()
|
|
1694
|
+
var int cur_h = self.content_height()
|
|
1695
|
+
if cur_w != prev_w {
|
|
1696
|
+
ev.resized = true
|
|
1697
|
+
}
|
|
1698
|
+
if cur_h != prev_h {
|
|
1699
|
+
ev.resized = true
|
|
1700
|
+
}
|
|
1701
|
+
if ev.resized {
|
|
1702
|
+
prev_w = cur_w
|
|
1703
|
+
prev_h = cur_h
|
|
1704
|
+
ev.width = cur_w
|
|
1705
|
+
ev.height = cur_h
|
|
1706
|
+
self.stamp_resize(true, cur_w, cur_h)
|
|
1707
|
+
self.relayout(0)
|
|
1708
|
+
}
|
|
1709
|
+
// The window refreshes the per-frame event sources (the
|
|
1710
|
+
// first-responder snapshot feeds the focus/blur drains), then the
|
|
1711
|
+
// app's synthesized `handle_events` pump drains registered
|
|
1712
|
+
// handlers — conformers without registrations inherit the
|
|
1713
|
+
// trait's empty default. One arm per registered control.
|
|
1714
|
+
nomen_window_focus_poll(self.handle)
|
|
1715
|
+
app.handle_events(ref self)
|
|
1716
|
+
app.frame(ref self, ev)
|
|
1404
1717
|
}
|
|
1405
|
-
if ev.resized {
|
|
1406
|
-
prev_w = cur_w
|
|
1407
|
-
prev_h = cur_h
|
|
1408
|
-
ev.width = cur_w
|
|
1409
|
-
ev.height = cur_h
|
|
1410
|
-
self.stamp_resize(true, cur_w, cur_h)
|
|
1411
|
-
self.relayout(0)
|
|
1412
|
-
}
|
|
1413
|
-
// The window refreshes the per-frame event sources (the
|
|
1414
|
-
// first-responder snapshot feeds the focus/blur drains), then the
|
|
1415
|
-
// app's synthesized `handle_events` pump drains registered
|
|
1416
|
-
// handlers — conformers without registrations inherit the
|
|
1417
|
-
// trait's empty default. One arm per registered control.
|
|
1418
|
-
nomen_window_focus_poll(self.handle)
|
|
1419
|
-
app.handle_events(ref self)
|
|
1420
|
-
app.frame(ref self, ev)
|
|
1421
1718
|
}
|
|
1719
|
+
// macOS convention: the app stays alive after the last window
|
|
1720
|
+
// closes — pump until Dock Quit (or quit()) ends the process, or
|
|
1721
|
+
// a Dock click reopens the window and the frame loop resumes.
|
|
1722
|
+
while !self.quit_flag() && !Window.reopen_flag() {
|
|
1723
|
+
Window.process_events()
|
|
1724
|
+
}
|
|
1725
|
+
if self.quit_flag() {
|
|
1726
|
+
return
|
|
1727
|
+
}
|
|
1728
|
+
// Reopened from the Dock: re-show and resume frames. start() runs
|
|
1729
|
+
// once — layout roots and handlers are already registered.
|
|
1730
|
+
self.show()
|
|
1731
|
+
self.relayout(1)
|
|
1732
|
+
prev_w = self.content_width()
|
|
1733
|
+
prev_h = self.content_height()
|
|
1422
1734
|
}
|
|
1423
1735
|
}
|
|
1424
1736
|
|
|
Binary file
|