basalt-appkit 0.0.0-rc5 → 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.
- package/native/CMakeLists.txt +16 -2
- package/native/appkit/AppKitAppWindow.h +24 -0
- package/native/appkit/AppKitImageLoader.h +48 -1
- package/native/appkit/AppKitImageLoader.mm +228 -10
- package/native/appkit/AppKitMenuBar.mm +58 -0
- package/native/appkit/AppKitMountingManager.h +34 -0
- package/native/appkit/AppKitMountingManager.mm +576 -9
- package/native/appkit/AppKitScrollView.h +48 -0
- package/native/appkit/AppKitScrollView.mm +210 -0
- package/native/appkit/AppKitTextInput.h +38 -1
- package/native/appkit/AppKitTextInput.mm +235 -8
- package/native/appkit/AppKitTextPeer.h +60 -0
- package/native/appkit/AppKitTextPeer.mm +307 -0
- package/native/appkit/AppKitTouchDispatcher.h +56 -0
- package/native/appkit/AppKitTouchDispatcher.mm +140 -0
- package/native/appkit/AppKitWindowControl.mm +38 -3
- package/native/appkit/ComponentRegistryAppKit.mm +20 -0
- package/native/appkit/CoreTextLayout.h +64 -2
- package/native/appkit/CoreTextLayout.mm +431 -71
- package/native/appkit/CoreTextLayoutManager.mm +57 -6
- package/native/appkit/FontRegistryCoreText.mm +6 -5
- package/native/appkit/PlatformServicesAppKit.mm +101 -20
- package/native/appkit/RnAppKitView.h +492 -0
- package/native/appkit/RnAppKitView.mm +2266 -23
- package/native/appkit/RnTextLayout.h +106 -0
- package/native/appkit/RnTextLayout.mm +321 -2
- package/native/appkit/main_appkit.mm +174 -3
- package/native/tests/test_appkit_accessibility.mm +289 -0
- package/native/tests/test_appkit_borders.mm +975 -0
- package/native/tests/test_appkit_fonts.mm +203 -0
- package/native/tests/test_appkit_image.mm +392 -17
- package/native/tests/test_appkit_input.mm +209 -0
- package/native/tests/test_appkit_mounting.mm +360 -0
- package/native/tests/test_appkit_scrollbar.mm +125 -0
- package/native/tests/test_appkit_scrollview.mm +371 -0
- package/native/tests/test_appkit_selection.mm +349 -0
- package/native/tests/test_appkit_services.mm +51 -1
- package/native/tests/test_appkit_text.mm +1628 -0
- package/native/tests/test_appkit_textinput.mm +819 -0
- package/native/tests/test_appkit_titlebar.mm +43 -0
- package/native/tests/test_appkit_view.mm +609 -0
- package/package.json +4 -3
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
// and to nothing else on the machine, which is what an app loading a bundled
|
|
12
12
|
// font wants and the only scope that needs no user consent.
|
|
13
13
|
//
|
|
14
|
-
//
|
|
15
|
-
// TextLayoutManager,
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
14
|
+
// `resolveFontFamily` had no reader when this was written: there was no Core
|
|
15
|
+
// Text TextLayoutManager, the seam phase 19 found. There is one now, and
|
|
16
|
+
// CoreTextLayout.mm's `fontFor` asks this for every paragraph with a
|
|
17
|
+
// `fontFamily`. tests/test_appkit_fonts.mm is where that path is checked,
|
|
18
|
+
// including a family the machine does not have, which is the case a loader
|
|
19
|
+
// exists for.
|
|
19
20
|
|
|
20
21
|
#include "FontRegistry.h"
|
|
21
22
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// macOS's half of the platform-services seam: clipboard, opening a URL, alerts.
|
|
2
2
|
|
|
3
3
|
#include "PlatformServices.h"
|
|
4
|
+
#include "SystemLocale.h"
|
|
4
5
|
#include "TestDialog.h"
|
|
5
6
|
|
|
6
7
|
#include <cstdint>
|
|
@@ -379,6 +380,67 @@ NSString *keyEquivalentFor(const std::string &shortcut, NSEventModifierFlags *ma
|
|
|
379
380
|
}
|
|
380
381
|
}
|
|
381
382
|
|
|
383
|
+
// Builds `entries` into `menu`, numbering every entry the way `walkMenuEntries`
|
|
384
|
+
// does: pre-order, counting separators and submenu parents, so a flat menu is
|
|
385
|
+
// numbered by position and nothing a caller already relied on moved.
|
|
386
|
+
//
|
|
387
|
+
// A parent carries no action and no tag. Choosing one is not a choice, it is
|
|
388
|
+
// opening a menu, and AppKit does not call an action for it anyway.
|
|
389
|
+
void addMenuEntries(NSMenu *menu,
|
|
390
|
+
const std::vector<MenuEntry> &entries,
|
|
391
|
+
RnAppKitMenuTarget *target,
|
|
392
|
+
int *next) {
|
|
393
|
+
for (const MenuEntry &entry : entries) {
|
|
394
|
+
const int index = (*next)++;
|
|
395
|
+
// Counted above, drawn or not: a role this desktop cannot perform keeps its
|
|
396
|
+
// index so the ones after it keep theirs. See menuEntryShown.
|
|
397
|
+
if (!menuEntryShown(entry)) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
if (entry.isSeparator()) {
|
|
401
|
+
[menu addItem:[NSMenuItem separatorItem]];
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
NSString *label = [NSString stringWithUTF8String:entry.label.c_str()];
|
|
406
|
+
if (label == nil) {
|
|
407
|
+
label = @"";
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (entry.isParent()) {
|
|
411
|
+
NSMenuItem *parent = [menu addItemWithTitle:label action:nullptr keyEquivalent:@""];
|
|
412
|
+
parent.enabled = entry.enabled;
|
|
413
|
+
NSMenu *submenu = [[NSMenu alloc] initWithTitle:label];
|
|
414
|
+
submenu.autoenablesItems = NO;
|
|
415
|
+
addMenuEntries(submenu, entry.submenu, target, next);
|
|
416
|
+
parent.submenu = submenu;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
NSEventModifierFlags mask = 0;
|
|
421
|
+
NSString *equivalent = keyEquivalentFor(entry.shortcut, &mask);
|
|
422
|
+
NSMenuItem *item = [menu addItemWithTitle:label
|
|
423
|
+
action:@selector(pick:)
|
|
424
|
+
keyEquivalent:equivalent];
|
|
425
|
+
item.keyEquivalentModifierMask = mask;
|
|
426
|
+
// Our own target even for a role, unlike the menu bar's `nil`: this has a
|
|
427
|
+
// promise to settle with the index, so it has to hear about the choice. The
|
|
428
|
+
// role is performed below, once, before the index is reported.
|
|
429
|
+
item.target = target;
|
|
430
|
+
item.enabled = entry.enabled;
|
|
431
|
+
item.tag = static_cast<NSInteger>(index);
|
|
432
|
+
|
|
433
|
+
// Both kinds draw a tick. NSMenu has no radio item, and a tick is what
|
|
434
|
+
// Apple's guidance puts beside the chosen member of an exclusive group, so
|
|
435
|
+
// this is the platform's answer rather than a shortfall. NSMenu manages the
|
|
436
|
+
// indicator column itself, so an unticked item still lines up with a ticked
|
|
437
|
+
// one and nothing has to reserve space.
|
|
438
|
+
if (entry.mark != MenuEntry::Mark::None) {
|
|
439
|
+
item.state = entry.checked ? NSControlStateValueOn : NSControlStateValueOff;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
382
444
|
} // namespace
|
|
383
445
|
|
|
384
446
|
void showMenu(const MenuRequest &request, MenuCallback onChosen) {
|
|
@@ -403,25 +465,8 @@ void showMenu(const MenuRequest &request, MenuCallback onChosen) {
|
|
|
403
465
|
menu.autoenablesItems = NO;
|
|
404
466
|
RnAppKitMenuTarget *target = [[RnAppKitMenuTarget alloc] init];
|
|
405
467
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (entry.isSeparator()) {
|
|
409
|
-
[menu addItem:[NSMenuItem separatorItem]];
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
NSEventModifierFlags mask = 0;
|
|
413
|
-
NSString *equivalent = keyEquivalentFor(entry.shortcut, &mask);
|
|
414
|
-
NSString *label = [NSString stringWithUTF8String:entry.label.c_str()];
|
|
415
|
-
NSMenuItem *item = [menu addItemWithTitle:label != nil ? label : @""
|
|
416
|
-
action:@selector(pick:)
|
|
417
|
-
keyEquivalent:equivalent];
|
|
418
|
-
item.keyEquivalentModifierMask = mask;
|
|
419
|
-
item.target = target;
|
|
420
|
-
item.enabled = entry.enabled;
|
|
421
|
-
// The index the caller gets back, which counts separators -- so it is
|
|
422
|
-
// the position in the vector rather than in this menu.
|
|
423
|
-
item.tag = static_cast<NSInteger>(i);
|
|
424
|
-
}
|
|
468
|
+
int next = 0;
|
|
469
|
+
addMenuEntries(menu, content.entries, target, &next);
|
|
425
470
|
|
|
426
471
|
NSPoint at;
|
|
427
472
|
if (content.x >= 0.0 && content.y >= 0.0) {
|
|
@@ -438,7 +483,18 @@ void showMenu(const MenuRequest &request, MenuCallback onChosen) {
|
|
|
438
483
|
// Blocks until the menu is dismissed, which is what a menu does. Safe
|
|
439
484
|
// here and not on the JavaScript thread; see above.
|
|
440
485
|
[menu popUpMenuPositioningItem:nil atLocation:at inView:anchor];
|
|
441
|
-
|
|
486
|
+
|
|
487
|
+
const int chosen = static_cast<int>(target.chosen);
|
|
488
|
+
// The platform's half of a role, before the caller's. `copy` has to have
|
|
489
|
+
// copied by the time JavaScript's `onSelect` runs, because an app whose
|
|
490
|
+
// handler reads the clipboard is reading what this just put there.
|
|
491
|
+
if (chosen >= 0) {
|
|
492
|
+
const MenuEntry *entry = menuEntryAt(content.entries, chosen);
|
|
493
|
+
if (entry != nullptr && !entry->role.empty()) {
|
|
494
|
+
performMenuRole(entry->role);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
onChosen(chosen);
|
|
442
498
|
}
|
|
443
499
|
});
|
|
444
500
|
}
|
|
@@ -538,3 +594,28 @@ bool isUiThread() {
|
|
|
538
594
|
}
|
|
539
595
|
|
|
540
596
|
} // namespace basalt
|
|
597
|
+
|
|
598
|
+
// --- The desktop's language --------------------------------------------------
|
|
599
|
+
|
|
600
|
+
namespace basalt {
|
|
601
|
+
|
|
602
|
+
// `characterDirectionForLanguage:` is ICU's own answer, which is what every
|
|
603
|
+
// Cocoa application uses to decide whether to mirror -- so an app on this host
|
|
604
|
+
// mirrors exactly when the desktop around it does. Asking the language rather
|
|
605
|
+
// than the full identifier is deliberate: `ar_EG` and `ar` read the same way,
|
|
606
|
+
// and the territory never decides direction.
|
|
607
|
+
SystemLocale systemLocale() {
|
|
608
|
+
SystemLocale locale;
|
|
609
|
+
NSLocale *const current = NSLocale.currentLocale;
|
|
610
|
+
locale.identifier = current.localeIdentifier.UTF8String != nullptr
|
|
611
|
+
? current.localeIdentifier.UTF8String
|
|
612
|
+
: "";
|
|
613
|
+
NSString *const language = [current objectForKey:NSLocaleLanguageCode];
|
|
614
|
+
if (language != nil) {
|
|
615
|
+
locale.rightToLeft = [NSLocale characterDirectionForLanguage:language] ==
|
|
616
|
+
NSLocaleLanguageDirectionRightToLeft;
|
|
617
|
+
}
|
|
618
|
+
return locale;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
} // namespace basalt
|