@gjsify/gtk-host 0.53.0 → 0.54.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/lib/esm/fonts.js +1 -1
- package/lib/types/adapters/react.d.ts +24 -39
- package/lib/types/attrs.d.ts +37 -49
- package/lib/types/fonts.d.ts +30 -44
- package/lib/types/host.d.ts +56 -78
- package/lib/types/policies.d.ts +159 -202
- package/lib/types/props.d.ts +23 -36
- package/lib/types/types.d.ts +73 -82
- package/package.json +5 -5
package/lib/esm/fonts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{isFontFace as e,resolveFontSources as t}from"./font-dir.js";import{describeFontFamilyMatch as n,matchFontFamilies as r,matchFontFamily as i}from"./font-families.js";import{ADWAITA_UI_FONT_FAMILY as a,GNOME_UI_FONT_POINT_SIZE as o,UI_FONT_POLICIES as s,planUiFont as c,planUiFontPolicy as l}from"./ui-font.js";import u from"gi://Gtk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://GLib?version=2.0";import p from"gi://PangoCairo?version=1.0";
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{isFontFace as e,resolveFontSources as t}from"./font-dir.js";import{describeFontFamilyMatch as n,matchFontFamilies as r,matchFontFamily as i}from"./font-families.js";import{ADWAITA_UI_FONT_FAMILY as a,GNOME_UI_FONT_POINT_SIZE as o,UI_FONT_POLICIES as s,planUiFont as c,planUiFontPolicy as l}from"./ui-font.js";import u from"gi://Gtk?version=4.0";import d from"gi://Gio?version=2.0";import f from"gi://GLib?version=2.0";import p from"gi://PangoCairo?version=1.0";import{CAIRO_FONT_TYPE_FT as m,fontErrorMessage as h,fontMapFamilies as g,isUnsupportedByFontMap as _,registerFontFaces as v}from"@gjsify/utils/font-map";function initFonts(e={}){let i=t({...e,env:{GJSIFY_FONT_DIR:f.getenv(`GJSIFY_FONT_DIR`)??void 0,GJSIFY_GTK_RUNTIME_FONT_DIR:f.getenv(`GJSIFY_GTK_RUNTIME_FONT_DIR`)??void 0}}),a=i.find(e=>e.origin===`app`)?.dir,o=[],s=[],c=[],l=[],u=[],m=e.expectedFamilies??[];if(i.length===0&&m.length===0)return{dir:a,sources:o,uiFont:void 0,registered:s,declined:c,unreachable:l,failed:u,families:[],matches:[],fontconfigFallback:!1};let h=[],_=p.FontMap.get_default(),y=i.map(e=>({source:e,registered:[],declined:[],unreachable:[],failed:[]})),b=!1;for(let e of y){let t=[];collectFaces(d.File.new_for_path(e.source.dir),t,e.failed);let n=v(t.sort(),_);(h.length===0||n.fontconfigFallback)&&(h=n.before),n.fontconfigFallback&&(b=!0),n.map!==void 0&&(_=n.map),e.registered.push(...n.registered),e.declined.push(...n.declined),e.unreachable.push(...n.unreachable),e.failed.push(...n.failed)}for(let e of y)s.push(...e.registered),c.push(...e.declined),l.push(...e.unreachable),u.push(...e.failed),o.push({...e.source,registered:e.registered,declined:e.declined,unreachable:e.unreachable,failed:e.failed});let x=g(_),S=i.length===0?[]:x.filter(e=>!h.includes(e)).sort(),C=r(m,x);captureUiFontBaseline();let w=e.uiFont===void 0?void 0:applyUiFontPolicy(e.uiFont);for(let e of u)console.warn(`initFonts: ${e.path} could not be read as an application font (${e.message}). Text asking for a family this application ships will render in a substituted one.`);for(let e of l)console.warn(`initFonts: ${e} is registered and its family is on the font map, but text asking for it will still render substituted: the font map had already resolved that family to the fallback and the cached answer cannot be invalidated. Call initFonts() before any text is laid out.`);for(let e of C)e.kind!==`exact`&&console.warn(`initFonts: ${n(e)}`);return{dir:a,sources:o,uiFont:w,registered:s,declined:c,unreachable:l,failed:u,families:S,matches:C,fontconfigFallback:b}}let y=!1,b;function captureUiFontBaseline(){if(y)return b;let e=u.Settings.get_default();if(e!==null)return b=e.gtk_font_name??void 0,y=!0,b}function uiFontBaseline(){return captureUiFontBaseline()}function applyUiFontPolicy(e){let t=typeof e==`string`?{policy:e}:e,n=t.settings===void 0?u.Settings.get_default():t.settings;if(n===null)return console.warn("applyUiFontPolicy: no Gtk.Settings — the toolkit is not initialised yet, so the policy was NOT applied. Call this after Gtk.init() (or from an application's `startup`), which is still before any window is built."),{next:void 0,kind:`uninitialised`,family:void 0,size:void 0};let r=captureUiFontBaseline(),i=l({...t,family:t.family??resolvedAdwaitaFamily(t.policy),current:n.gtk_font_name??void 0,baseline:r});return i.next===void 0||(n.gtk_font_name=i.next),i}function resolvedAdwaitaFamily(e){if(e!==`adwaita`)return;let t=adwaitaUiFontAvailability();if(t.match.family!==void 0)return t.match.family;console.warn(`applyUiFontPolicy: "${t.family}" is ${t.match.kind} on this font map, so asking for it will render in a substituted family. Register the runtime bundle's faces with initFonts() first, and check adwaitaUiFontAvailability() before offering this policy.`)}function adwaitaUiFontAvailability(e=a){let t=i(e,g(p.FontMap.get_default()));return{family:e,match:t,available:t.kind!==`absent`}}function collectFaces(t,n,r){try{let i=t.enumerate_children(`standard::name,standard::type`,d.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,null);for(let t=i.next_file(null);t!==null;t=i.next_file(null)){let a=i.get_child(t),o=a.get_path();o!==null&&(t.get_file_type()===d.FileType.DIRECTORY?collectFaces(a,n,r):e(t.get_name())&&n.push(o))}}catch(e){r.push({path:t.get_path()??``,message:h(e)})}}export{a as ADWAITA_UI_FONT_FAMILY,m as CAIRO_FONT_TYPE_FT,o as GNOME_UI_FONT_POINT_SIZE,s as UI_FONT_POLICIES,adwaitaUiFontAvailability,applyUiFontPolicy,n as describeFontFamilyMatch,initFonts,_ as isUnsupportedByFontMap,r as matchFontFamilies,i as matchFontFamily,c as planUiFont,l as planUiFontPolicy,t as resolveFontSources,uiFontBaseline};
|
|
@@ -7,12 +7,10 @@ export type ReactProps = Record<string, unknown>;
|
|
|
7
7
|
/**
|
|
8
8
|
* The HostConfig, exported because it IS the contract.
|
|
9
9
|
*
|
|
10
|
-
* `react.spec.ts` builds a second reconciler over a Proxy of this object to read
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* configured reconciler (a `LegacyRoot`, a different event priority) without
|
|
15
|
-
* restating the mapping.
|
|
10
|
+
* `react.spec.ts` builds a second reconciler over a Proxy of this object to read the member set the
|
|
11
|
+
* INSTALLED `react-reconciler` asks for, so a version that starts asking for something new fails a
|
|
12
|
+
* test instead of returning `undefined` in a commit. It is also the seam for a consumer who needs
|
|
13
|
+
* a differently configured reconciler (a `LegacyRoot`, a different event priority).
|
|
16
14
|
*/
|
|
17
15
|
export declare const gtkHostConfig: {
|
|
18
16
|
supportsMutation: boolean;
|
|
@@ -31,15 +29,14 @@ export declare const gtkHostConfig: {
|
|
|
31
29
|
/**
|
|
32
30
|
* `false`, always — one text path instead of two.
|
|
33
31
|
*
|
|
34
|
-
* `true` would tell React to skip text instances for this element and leave
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* `
|
|
38
|
-
* `true` would move that decision into the adapter, where it would be a
|
|
32
|
+
* `true` would tell React to skip text instances for this element and leave the string in
|
|
33
|
+
* `props.children` for the adapter to write. The host already owns that translation: a text NODE
|
|
34
|
+
* is concatenated into the descriptor's `textSink`, and a widget without one refuses text BY
|
|
35
|
+
* TAG NAME. Answering `true` would move that decision into the adapter, where it would be a
|
|
39
36
|
* widget-knowledge test — the one thing ADR 0027 § 7 forbids an adapter.
|
|
40
37
|
*
|
|
41
|
-
* It also keeps `resetTextContent` unreachable: React sets the `ContentReset`
|
|
42
|
-
*
|
|
38
|
+
* It also keeps `resetTextContent` unreachable: React sets the `ContentReset` flag only when
|
|
39
|
+
* `shouldSetTextContent` was true for the PREVIOUS props.
|
|
43
40
|
*/
|
|
44
41
|
shouldSetTextContent: () => boolean;
|
|
45
42
|
getRootHostContext: () => object;
|
|
@@ -60,14 +57,11 @@ export declare const gtkHostConfig: {
|
|
|
60
57
|
/**
|
|
61
58
|
* The priority an update gets when React is not already inside a lane.
|
|
62
59
|
*
|
|
63
|
-
* React DOM derives this from the DOM event being handled (a click is
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* so it lands when `scheduler` next runs, i.e. on the next GLib main-loop
|
|
69
|
-
* iteration. `flushSync` is the escape hatch, and the spec pumps the main
|
|
70
|
-
* context to prove the scheduled path works at all under GJS.
|
|
60
|
+
* React DOM derives this from the DOM event being handled (a click is discrete, a scroll
|
|
61
|
+
* continuous). A GTK signal handler is not a DOM event and there is no ambient event to read, so
|
|
62
|
+
* every update is a default-lane one — the same answer `react-art` and `react-nil` give.
|
|
63
|
+
* Consequence, stated because it is load-bearing: a `setState` from a GTK handler is CONCURRENT,
|
|
64
|
+
* so it lands when `scheduler` next runs, i.e. on the next GLib main-loop iteration.
|
|
71
65
|
*/
|
|
72
66
|
resolveUpdatePriority: () => number;
|
|
73
67
|
shouldAttemptEagerTransition: () => boolean;
|
|
@@ -81,30 +75,21 @@ export declare const gtkHostConfig: {
|
|
|
81
75
|
removeChild: (_parent: HostElement, child: HostNode) => void;
|
|
82
76
|
removeChildFromContainer: (_container: HostElement, child: HostNode) => void;
|
|
83
77
|
/**
|
|
84
|
-
* React clears the root before its FIRST commit
|
|
85
|
-
*
|
|
78
|
+
* React clears the root before its FIRST commit, and the application's own chrome must survive it.
|
|
79
|
+
* In the DOM that discards leftover markup. Here the container is a widget the application
|
|
80
|
+
* built and filled, so this clears what the HOST put there (the shadow children) and never
|
|
81
|
+
* `el.foreign`, which `adopt` recorded precisely so placement can offset past it.
|
|
86
82
|
*
|
|
87
|
-
* `
|
|
88
|
-
*
|
|
89
|
-
* container. In the DOM that discards leftover markup. Here the container is a
|
|
90
|
-
* widget the application built and filled, so this clears what the HOST put
|
|
91
|
-
* there (the shadow children) and never `el.foreign`, which `adopt` recorded
|
|
92
|
-
* precisely so placement can offset past it.
|
|
93
|
-
*
|
|
94
|
-
* `destroy` rather than `remove`, for the same reason `removeChild` uses it:
|
|
95
|
-
* GJS blocks JS callbacks during GC, so a detached node keeps its handlers
|
|
96
|
-
* for the life of the process.
|
|
83
|
+
* `destroy` rather than `remove`, for the same reason `removeChild` uses it: GJS blocks JS
|
|
84
|
+
* callbacks during GC, so a detached node keeps its handlers for the life of the process.
|
|
97
85
|
*/
|
|
98
86
|
clearContainer: (container: HostElement) => void;
|
|
99
87
|
/**
|
|
100
88
|
* Diff AND apply — one phase, because React 19 deleted the other one.
|
|
101
89
|
*
|
|
102
|
-
* The argument list is the change with teeth: React
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* removed from the FRONT, so an adapter that kept the old signature would read
|
|
106
|
-
* the type string as its payload and iterate a string — which is why this is
|
|
107
|
-
* spelled out rather than left to positional luck.
|
|
90
|
+
* The argument list is the change with teeth: React 19 removed the `updatePayload` slot from the
|
|
91
|
+
* FRONT, so an adapter that kept the old signature would read the type string as its payload
|
|
92
|
+
* and iterate a string.
|
|
108
93
|
*/
|
|
109
94
|
commitUpdate: (instance: HostElement, _type: string, prevProps: ReactProps, nextProps: ReactProps) => void;
|
|
110
95
|
commitTextUpdate: (textInstance: HostText, _oldText: string, newText: string) => void;
|
package/lib/types/attrs.d.ts
CHANGED
|
@@ -7,31 +7,28 @@ import type { HostNode } from './types.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* A `notify::` handler.
|
|
9
9
|
*
|
|
10
|
-
* The host strips the emitting object
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* nothing to do with the GIR it read.
|
|
10
|
+
* The host strips the emitting object, so what reaches the callback is the ParamSpec alone. Declared
|
|
11
|
+
* HERE rather than in the generated file because it is the same for every property in GTK — and a
|
|
12
|
+
* generator that emitted it would have to import GObject for a type that has nothing to do with
|
|
13
|
+
* the GIR it read.
|
|
15
14
|
*/
|
|
16
15
|
export type NotifyHandler = (pspec: GObject.ParamSpec) => void;
|
|
17
16
|
declare const outParam: unique symbol;
|
|
18
17
|
/**
|
|
19
18
|
* A signal parameter GIR declares `out`/`inout` with `caller-allocates="0"`.
|
|
20
19
|
*
|
|
21
|
-
* GJS still passes an argument in that position, and what it holds is whatever
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* `
|
|
25
|
-
*
|
|
20
|
+
* GJS still passes an argument in that position, and what it holds is whatever was in the memory
|
|
21
|
+
* the marshaller allocated: measured on gjs 1.88.1 / GTK 4.22.4, a handler on
|
|
22
|
+
* `Gtk.SpinButton::input` receives `new_value` as `6.9526682391035e-310`, and one on
|
|
23
|
+
* `Gtk.Editable::insert-text` receives `position` as `1711500784`. Both arrive as ordinary numbers.
|
|
24
|
+
* Nothing warns.
|
|
26
25
|
*
|
|
27
|
-
* So the slot is DECLARED — dropping it would silently shift every parameter
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* naming the position, which is the only place a reader would have looked.
|
|
26
|
+
* So the slot is DECLARED — dropping it would silently shift every parameter after it — and given
|
|
27
|
+
* a type nothing can be read out of, and nothing but itself assigns to. Annotating the parameter
|
|
28
|
+
* `number` is then a compile error naming the position.
|
|
31
29
|
*
|
|
32
|
-
* `caller-allocates="1"` is a different thing and keeps its real type: there the
|
|
33
|
-
*
|
|
34
|
-
* is handed a `Gdk.Rectangle`.
|
|
30
|
+
* `caller-allocates="1"` is a different thing and keeps its real type: there the callee is handed
|
|
31
|
+
* a live object to FILL, as `Gtk.Overlay::get-child-position` is handed a `Gdk.Rectangle`.
|
|
35
32
|
*/
|
|
36
33
|
export type OutParam = {
|
|
37
34
|
readonly [outParam]: never;
|
|
@@ -39,10 +36,9 @@ export type OutParam = {
|
|
|
39
36
|
/**
|
|
40
37
|
* What may appear as a child, mirroring Solid's own `JSX.Element`.
|
|
41
38
|
*
|
|
42
|
-
* The shape is copied from `solid-js/types/jsx.d.ts` because a renderer's element
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* not. Substituting our host node for the DOM's `Node` is the only change.
|
|
39
|
+
* The shape is copied from `solid-js/types/jsx.d.ts` because a renderer's element union is not a free
|
|
40
|
+
* choice: a string, a number and a boolean are all legal children there, an array of children is
|
|
41
|
+
* legal recursively, and a FUNCTION is not.
|
|
46
42
|
*/
|
|
47
43
|
export type ElementChild = HostNode | ElementChildren | string | number | boolean | null | undefined;
|
|
48
44
|
export interface ElementChildren extends Array<ElementChild> {
|
|
@@ -50,10 +46,9 @@ export interface ElementChildren extends Array<ElementChild> {
|
|
|
50
46
|
/**
|
|
51
47
|
* Add the `.once` spelling of every event prop, without generating 2× the members.
|
|
52
48
|
*
|
|
53
|
-
* `signals.ts` accepts `onClickedOnce` for every `onClicked`, including every
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* declaration merging.
|
|
49
|
+
* `signals.ts` accepts `onClickedOnce` for every `onClicked`, including every `onNotifyFooOnce`,
|
|
50
|
+
* which would be another ~1000 generated members. A mapped type derives them from the interface
|
|
51
|
+
* instead — including the ones a consumer adds by declaration merging.
|
|
57
52
|
*/
|
|
58
53
|
export type WithOnce<T> = T & {
|
|
59
54
|
[K in keyof T & string as K extends `on${string}` ? `${K}Once` : never]?: T[K];
|
|
@@ -65,11 +60,11 @@ export interface SlotAttribute {
|
|
|
65
60
|
/**
|
|
66
61
|
* GTK's ARIA surface, on every element of every dialect. Read by `setAccessibility()`.
|
|
67
62
|
*
|
|
68
|
-
* ONE OBJECT, not 53 flat `aria*` props, and the four reasons are in `setAccessibility`'s
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
63
|
+
* ONE OBJECT, not 53 flat `aria*` props, and the four reasons are in `setAccessibility`'s own
|
|
64
|
+
* header — the load-bearing one being that TypeScript exempts a hyphenated JSX attribute from
|
|
65
|
+
* excess-property checking while a key in a fresh object literal is checked.
|
|
66
|
+
* `AccessibilityAttributes` is GENERATED, because the names and their value types are GTK's and are
|
|
67
|
+
* stated nowhere a ParamSpec can be read from.
|
|
73
68
|
*/
|
|
74
69
|
export interface AccessibilityAttribute {
|
|
75
70
|
accessibility?: AccessibilityAttributes | null;
|
|
@@ -77,12 +72,10 @@ export interface AccessibilityAttribute {
|
|
|
77
72
|
/**
|
|
78
73
|
* The `on:<raw-signal-name>` escape hatch, typed.
|
|
79
74
|
*
|
|
80
|
-
* `parseEventProp` takes `on:` + a signal name verbatim, which is how a signal
|
|
81
|
-
*
|
|
82
|
-
* is
|
|
83
|
-
*
|
|
84
|
-
* An inline arrow's parameter arrives as `never` here, which is the price of an
|
|
85
|
-
* escape hatch that carries no signal-specific knowledge.
|
|
75
|
+
* `parseEventProp` takes `on:` + a signal name verbatim, which is how a signal whose name resists
|
|
76
|
+
* the camelCase derivation gets bound at all. The handler type is deliberately the widest one that
|
|
77
|
+
* is not `any`: parameters of `never` accept a handler declared with any parameters, so nothing a
|
|
78
|
+
* consumer writes is refused.
|
|
86
79
|
*/
|
|
87
80
|
export interface RawSignalAttributes {
|
|
88
81
|
[key: `on:${string}`]: ((...args: never[]) => unknown) | undefined;
|
|
@@ -107,25 +100,20 @@ export interface JsxAttributes<T> extends AccessibilityAttribute, SlotAttribute,
|
|
|
107
100
|
/**
|
|
108
101
|
* Per-element attributes for Vue.
|
|
109
102
|
*
|
|
110
|
-
* Deliberately NOT `JsxAttributes`: Vue supplies `ref` and `key` itself through
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* leave the property unusable, so the Vue surface adds only what Vue does not —
|
|
114
|
-
* and `children` is a SLOT in Vue, never a prop.
|
|
103
|
+
* Deliberately NOT `JsxAttributes`: Vue supplies `ref` and `key` itself through `VNodeProps`, which
|
|
104
|
+
* every registered component's props are intersected with. Declaring our own `ref` would intersect
|
|
105
|
+
* two different `ref` types and could leave the property unusable.
|
|
115
106
|
*/
|
|
116
107
|
export interface VueAttributes extends AccessibilityAttribute, SlotAttribute, RawSignalAttributes {
|
|
117
108
|
}
|
|
118
109
|
/**
|
|
119
110
|
* The properties whose GObject type is a `GMenuModel`, in both spellings.
|
|
120
111
|
*
|
|
121
|
-
* A NAME LIST, not a type test, and the reason is measured
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* buttons, the popover menu and the menu bar; `extra-menu` on the text widgets;
|
|
127
|
-
* `secondary-menu` on `AdwToolbarView`'s header bar), and `type-tests/` holds the
|
|
128
|
-
* widening against real markup in both dialects.
|
|
112
|
+
* A NAME LIST, not a type test, and the reason is measured: the obvious `Gio.MenuModel extends
|
|
113
|
+
* NonNullable<T[K]> ? …` also matches every property typed as a wider GObject — `Gio.MenuModel
|
|
114
|
+
* extends GObject.Object` is TRUE — so the widening would leak onto properties that take an
|
|
115
|
+
* entirely different object. The names below are the whole set on the shipped table, and
|
|
116
|
+
* `type-tests/` holds the widening against real markup in both dialects.
|
|
129
117
|
*/
|
|
130
118
|
type MenuModelProp = 'menuModel' | 'menu-model' | 'extraMenu' | 'extra-menu' | 'secondaryMenu' | 'secondary-menu';
|
|
131
119
|
/**
|
package/lib/types/fonts.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import Gtk from 'gi://Gtk?version=4.0';
|
|
2
|
+
import { type FontFaceFailure } from '@gjsify/utils/font-map';
|
|
2
3
|
import { type FontFamilyMatch } from './font-families.js';
|
|
3
4
|
import { type FontSource, type ResolveFontSourcesOptions } from './font-dir.js';
|
|
4
5
|
import { type PlanUiFontOptions, type UiFontPlan, type UiFontPolicy } from './ui-font.js';
|
|
5
6
|
export { describeFontFamilyMatch, matchFontFamilies, matchFontFamily, type FontFamilyMatch, type FontFamilyMatchKind, } from './font-families.js';
|
|
7
|
+
export { CAIRO_FONT_TYPE_FT, isUnsupportedByFontMap } from '@gjsify/utils/font-map';
|
|
8
|
+
export type { FontFaceFailure } from '@gjsify/utils/font-map';
|
|
6
9
|
export { ADWAITA_UI_FONT_FAMILY, GNOME_UI_FONT_POINT_SIZE, UI_FONT_POLICIES, planUiFont, planUiFontPolicy, type PlanUiFontOptions, type PlanUiFontPolicyOptions, type UiFontPlan, type UiFontPlanKind, type UiFontPolicy, } from './ui-font.js';
|
|
7
10
|
export { resolveFontSources, type FontSource, type ResolveFontSourcesOptions } from './font-dir.js';
|
|
8
11
|
/**
|
|
@@ -36,11 +39,6 @@ export interface InitFontsOptions extends Omit<ResolveFontSourcesOptions, 'env'>
|
|
|
36
39
|
*/
|
|
37
40
|
readonly expectedFamilies?: readonly string[];
|
|
38
41
|
}
|
|
39
|
-
/** A face the font map would not take, and why. */
|
|
40
|
-
export interface FontFaceFailure {
|
|
41
|
-
readonly path: string;
|
|
42
|
-
readonly message: string;
|
|
43
|
-
}
|
|
44
42
|
/**
|
|
45
43
|
* A {@link FontSource} and the faces IT contributed.
|
|
46
44
|
*
|
|
@@ -61,6 +59,14 @@ export interface FontSourceOutcome extends FontSource {
|
|
|
61
59
|
readonly registered: readonly string[];
|
|
62
60
|
/** Faces from THIS directory the font map declined — see {@link isUnsupportedByFontMap}. */
|
|
63
61
|
readonly declined: readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* Faces from THIS directory that are on the map and that no layout can be served by — the map had
|
|
64
|
+
* already resolved their family to the fallback and caches that answer. Disjoint from
|
|
65
|
+
* {@link declined} and a subset of {@link registered}; `FontFaceRegistration.unreachable` in
|
|
66
|
+
* `@gjsify/utils/font-map` owns the reading and the fresh-map fallback that normally clears this
|
|
67
|
+
* list, so a non-empty one means that fallback was unavailable and the substitution is real.
|
|
68
|
+
*/
|
|
69
|
+
readonly unreachable: readonly string[];
|
|
64
70
|
/** Faces from THIS directory that failed otherwise, plus the directory itself if unreadable. */
|
|
65
71
|
readonly failed: readonly FontFaceFailure[];
|
|
66
72
|
}
|
|
@@ -98,6 +104,19 @@ export interface InitFontsResult {
|
|
|
98
104
|
* {@link isUnsupportedByFontMap}.
|
|
99
105
|
*/
|
|
100
106
|
readonly declined: readonly string[];
|
|
107
|
+
/**
|
|
108
|
+
* Faces that are on the map and that no layout can be served by, across every {@link sources}
|
|
109
|
+
* entry: the map resolved their family to the fallback before the face arrived and caches that
|
|
110
|
+
* answer, so registering the face changed `list_families()` and nothing else. A SUBSET of
|
|
111
|
+
* {@link registered} — the face really is on the map and `get_family` answers its family — which
|
|
112
|
+
* is why it is reported beside the flat lists rather than inside them.
|
|
113
|
+
*
|
|
114
|
+
* EMPTY wherever the fontconfig fallback took over, which is the whole point of it: then a fresh
|
|
115
|
+
* map serves the faces and there is nothing left to say. Non-empty means that fallback was
|
|
116
|
+
* unavailable (`PANGOCAIRO_BACKEND` pinned, no fontconfig configuration, no fc backend) and the
|
|
117
|
+
* substitution will happen whatever the application does next.
|
|
118
|
+
*/
|
|
119
|
+
readonly unreachable: readonly string[];
|
|
101
120
|
/**
|
|
102
121
|
* Faces that failed for any other reason, across every {@link sources} entry. Each was warned
|
|
103
122
|
* about; none threw.
|
|
@@ -135,7 +154,7 @@ export interface InitFontsResult {
|
|
|
135
154
|
readonly matches: readonly FontFamilyMatch[];
|
|
136
155
|
/**
|
|
137
156
|
* `true` when this call REPLACED the process's default font map with a fontconfig-backed one
|
|
138
|
-
* so the faces could be registered at all — see
|
|
157
|
+
* so the faces could be registered at all — see `probeFontconfigMap` in `@gjsify/utils/font-map`.
|
|
139
158
|
*
|
|
140
159
|
* Reported because it is a whole-application consequence of one call: every widget created
|
|
141
160
|
* afterwards renders through FreeType instead of the platform rasteriser. It happens only
|
|
@@ -145,42 +164,6 @@ export interface InitFontsResult {
|
|
|
145
164
|
*/
|
|
146
165
|
readonly fontconfigFallback: boolean;
|
|
147
166
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Did the font map decline runtime registration outright?
|
|
150
|
-
*
|
|
151
|
-
* `pango_font_map_add_font_file()` is a vfunc, and the CoreText map implements none — so on macOS
|
|
152
|
-
* the call falls through to the base implementation, which answers `G_IO_ERROR_NOT_SUPPORTED`.
|
|
153
|
-
* That is not a failure to report: macOS is already correct declaratively, because the bundle's
|
|
154
|
-
* `ATSApplicationFontsPath` had the OS activate the staged directory before the process started,
|
|
155
|
-
* and the ordering makes the runtime call the wrong tool there rather than merely a redundant one
|
|
156
|
-
* — `pango_core_text_font_map_changed()` only bumps a serial, there is no
|
|
157
|
-
* `kCTFontManagerRegisteredFontsChangedNotification` observer and no re-scan path in
|
|
158
|
-
* `pangocoretext-fontmap.c`, so a face registered after the map initialises could not be recovered
|
|
159
|
-
* by poking it anyway.
|
|
160
|
-
*
|
|
161
|
-
* Keyed on the ERROR rather than on `process.platform`, which is the difference between a
|
|
162
|
-
* capability test and a guess about who is asking. It costs no `gjsify.os` declaration (this
|
|
163
|
-
* package makes no OS decision, and ADR 0018's candidate set is derived from the code that reads
|
|
164
|
-
* the host), and it stays right for any other map that declines. The OS name was never the thing
|
|
165
|
-
* being asked — which stopped being hypothetical: the backend is whichever one is selected rather
|
|
166
|
-
* than one per platform, and `@gjsify/node-gi`'s loader selects `PANGOCAIRO_BACKEND=fc` on the
|
|
167
|
-
* bundled windowing runtime (ADR 0038 § Amendment 3), so a darwin process on it reaches this
|
|
168
|
-
* arm's other side and REGISTERS the faces. A `process.platform` branch would have had to be
|
|
169
|
-
* found and reversed instead.
|
|
170
|
-
*/
|
|
171
|
-
export declare function isUnsupportedByFontMap(error: unknown): boolean;
|
|
172
|
-
/**
|
|
173
|
-
* `CAIRO_FONT_TYPE_FT` from `cairo.h` — the value `pango_cairo_font_map_new_for_font_type()` maps
|
|
174
|
-
* to its fontconfig backend.
|
|
175
|
-
*
|
|
176
|
-
* A literal rather than `gi://cairo`'s `FontType.FT`: this module runs on both legs (GJS and
|
|
177
|
-
* `@gjsify/node-gi`), and the enum is part of cairo's ABI, so importing a fourth namespace to
|
|
178
|
-
* spell one stable integer would add a load-time dependency for nothing.
|
|
179
|
-
*
|
|
180
|
-
* Exported so `fonts.spec.ts`'s independent probe spells the SAME integer rather than a second
|
|
181
|
-
* literal that could drift from this one silently — see § duplication instead of a helper.
|
|
182
|
-
*/
|
|
183
|
-
export declare const CAIRO_FONT_TYPE_FT = 1;
|
|
184
167
|
/**
|
|
185
168
|
* Register every face in the application's shipped font directory with the default font map.
|
|
186
169
|
*
|
|
@@ -188,8 +171,11 @@ export declare const CAIRO_FONT_TYPE_FT = 1;
|
|
|
188
171
|
* fontconfig backend rather than tidiness: it caches the FONTSET resolved for a description and
|
|
189
172
|
* `add_font_file` does not invalidate it, so a `Pango.Layout` that measured the family first keeps
|
|
190
173
|
* measuring the fallback for the life of the process even though the family is then in
|
|
191
|
-
* `list_families()`. win32 clears its cache instead and recovers, so registering early is free
|
|
192
|
-
*
|
|
174
|
+
* `list_families()`. win32 clears its cache instead and recovers, so registering early is free there
|
|
175
|
+
* and unrecoverable-if-missed on Linux (measured both ways; `fonts.spec.ts`). Calling it late is no
|
|
176
|
+
* longer SILENTLY wrong, though: `registerFontFaces` measures what it registered, replaces the default
|
|
177
|
+
* map when a face turned out to be unserved, and reports what it could not rescue in
|
|
178
|
+
* {@link InitFontsResult.unreachable} — see the file header for what that leaves of the rule.
|
|
193
179
|
*
|
|
194
180
|
* Nothing here is eager: this
|
|
195
181
|
* package is the element model renderers bind to and owns no application lifecycle, and a
|
package/lib/types/host.d.ts
CHANGED
|
@@ -24,23 +24,22 @@ export declare function setEventHandler(el: HostElement, prop: string, next: ((.
|
|
|
24
24
|
/**
|
|
25
25
|
* The ARIA object, diffed against the one it replaces.
|
|
26
26
|
*
|
|
27
|
-
* ONE GROUPED PROP RATHER THAN 53 FLAT `aria*` ONES,
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* `
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* mechanism — so this adds one reserved key to the host, not 53.
|
|
27
|
+
* ONE GROUPED PROP RATHER THAN 53 FLAT `aria*` ONES, for measured reasons. (1)
|
|
28
|
+
* TypeScript exempts every hyphen-containing JSX attribute from excess-property checking —
|
|
29
|
+
* the measurement `emit-types.mts` already records for the kebab property spellings — so a
|
|
30
|
+
* flat `aria-labell` would be accepted in silence, while a key inside a fresh object literal
|
|
31
|
+
* IS checked. (2) The ARIA names collide with the widget's own properties: `label`,
|
|
32
|
+
* `orientation`, `checked`, `expanded` and `selected` are all both, and `orientation` is
|
|
33
|
+
* settable on a `GtkLabel` that implements no `GtkOrientable` at all — one object keeps the
|
|
34
|
+
* two vocabularies apart by construction instead of by prefix. (3) The other surface over
|
|
35
|
+
* this vocabulary already spells it this way: a `.blp` author writes `accessibility {
|
|
36
|
+
* label: "…"; }` (ADR 0034). (4) `setProp` already has this shape for `layout`, so this adds
|
|
37
|
+
* one reserved key to the host, not 53.
|
|
39
38
|
*
|
|
40
39
|
* REFUSED ON THE CLASS, not on the widget: every framework builds bottom-up, so props are
|
|
41
40
|
* authored long before materialisation, and asking the instance would report
|
|
42
|
-
* `<gtk-string-list accessibility={…}>` from inside a later `materialize` rather than at
|
|
43
|
-
* call that wrote it.
|
|
41
|
+
* `<gtk-string-list accessibility={…}>` from inside a later `materialize` rather than at
|
|
42
|
+
* the call that wrote it.
|
|
44
43
|
*
|
|
45
44
|
* The plan is built BEFORE anything is recorded, for the reason the property path states:
|
|
46
45
|
* `el.accessibility` is replayed verbatim by `replayInto`, so a refused value kept there
|
|
@@ -55,32 +54,23 @@ export declare function insert(node: HostNode, parent: HostElement, anchor?: Hos
|
|
|
55
54
|
/**
|
|
56
55
|
* TWO facts, not one: it says it is an element, and it carries a descriptor.
|
|
57
56
|
*
|
|
58
|
-
* `kind` alone is a plain string a GObject wrapper could carry; the descriptor is
|
|
59
|
-
*
|
|
60
|
-
*
|
|
57
|
+
* `kind` alone is a plain string a GObject wrapper could carry; the descriptor is what
|
|
58
|
+
* every host op actually dereferences. Checking both keeps the refusal from being either
|
|
59
|
+
* paranoid or fooled.
|
|
61
60
|
*
|
|
62
|
-
* Exported because the Vue adapter
|
|
63
|
-
*
|
|
64
|
-
* from the raw widget `<Teleport :to="el">` hands through. A predicate stated in
|
|
65
|
-
* two places is a predicate that can disagree with itself about what a node is.
|
|
61
|
+
* Exported because the Vue adapter needs the question before `adopt`, to tell a host
|
|
62
|
+
* parent from the raw widget `<Teleport :to="el">` hands through.
|
|
66
63
|
*/
|
|
67
64
|
export declare function isHostElement(value: unknown): value is HostElement;
|
|
68
65
|
/**
|
|
69
66
|
* Name a foreign value the way its owner would recognise it.
|
|
70
67
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* ORDER IS LOAD-BEARING, and it is measured rather than reasoned: under gjs
|
|
79
|
-
* 1.88.1 `({}).constructor.$gtype` EXISTS and `GObject.type_name` calls it
|
|
80
|
-
* `JSObject`. So a `$gtype`-first version names every object literal — and every
|
|
81
|
-
* DOM-ish stub, which is an object literal — `JSObject`, and the host's own
|
|
82
|
-
* documented `a plain object` fallback was unreachable for exactly the shape it
|
|
83
|
-
* names. `tagName` first, and `JSObject` treated as the absence of a GType.
|
|
68
|
+
* ORDER IS LOAD-BEARING, and it is measured rather than reasoned: under gjs 1.88.1
|
|
69
|
+
* `({}).constructor.$gtype` EXISTS and `GObject.type_name` calls it `JSObject`. A
|
|
70
|
+
* `$gtype`-first version would therefore name every object literal — and every DOM-ish
|
|
71
|
+
* stub, which is an object literal — `JSObject`, and the `a plain object` fallback would be
|
|
72
|
+
* unreachable for exactly the shape it names. `tagName` first, `JSObject` treated as the
|
|
73
|
+
* absence of a GType.
|
|
84
74
|
*/
|
|
85
75
|
export declare function describeValue(value: unknown): string;
|
|
86
76
|
/** Detach only — reversible. Frameworks move nodes; `remove` must not destroy one. */
|
|
@@ -88,30 +78,25 @@ export declare function remove(node: HostNode): void;
|
|
|
88
78
|
/**
|
|
89
79
|
* Destroy every child of `parent`, bounded.
|
|
90
80
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* list. Unbounded, that is a hang rather than GTK's usual exit 0.
|
|
97
|
-
*
|
|
98
|
-
* This replaces a `clearContainer` that had no callers anywhere and DETACHED rather
|
|
99
|
-
* than destroyed — the wrong half for every caller that wanted it, and a name React's
|
|
100
|
-
* own HostConfig already uses for the destroying kind.
|
|
81
|
+
* Every walk over `next` goes through `childSnapshot` so the bound cannot be forgotten at a
|
|
82
|
+
* new call site, and this is the walk where the malformed link actually appears: `insert(
|
|
83
|
+
* node, parent, node)` is a defined DOM no-op, so Solid's adjacent-swap fast path emits it
|
|
84
|
+
* against a CONTAINER's child list. Unbounded, that is a hang rather than GTK's usual
|
|
85
|
+
* exit 0.
|
|
101
86
|
*/
|
|
102
87
|
export declare function destroyChildren(parent: HostElement): void;
|
|
103
88
|
/**
|
|
104
89
|
* Disconnect a node's handlers WITHOUT touching the tree.
|
|
105
90
|
*
|
|
106
|
-
* The narrow half of `destroy`, and it exists because a framework can tell us "this
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
91
|
+
* The narrow half of `destroy`, and it exists because a framework can tell us "this node is
|
|
92
|
+
* gone" while still holding its sibling links: Solid disposes a per-node scope BEFORE its
|
|
93
|
+
* reconciler runs, and `reconcileArrays` opens with `getNextSibling(last)`. Unlinking there
|
|
94
|
+
* made every trailing insertion append at the end of the parent instead of before the
|
|
95
|
+
* marker.
|
|
111
96
|
*
|
|
112
|
-
* The leak this closes is about handlers, not links — GJS blocks JS callbacks
|
|
113
|
-
*
|
|
114
|
-
*
|
|
97
|
+
* The leak this closes is about handlers, not links — GJS blocks JS callbacks during GC, so
|
|
98
|
+
* an undisconnected handler outlives its widget. The framework's own `removeNode` still
|
|
99
|
+
* does the unlinking, in its own order.
|
|
115
100
|
*/
|
|
116
101
|
export declare function disconnectHandlers(el: HostElement): void;
|
|
117
102
|
/**
|
|
@@ -128,43 +113,36 @@ export declare function destroy(node: HostNode): void;
|
|
|
128
113
|
/**
|
|
129
114
|
* Put a host tree inside an existing GTK container the application owns.
|
|
130
115
|
*
|
|
131
|
-
* The container is resolved through the SAME table as every other parent
|
|
132
|
-
* `
|
|
133
|
-
* `
|
|
134
|
-
* method name here would be the generic `add` that GTK4 deliberately removed.
|
|
116
|
+
* The container is resolved through the SAME table as every other parent, so an
|
|
117
|
+
* application's own `GObject.registerClass` subclass inherits its ancestor's policy.
|
|
118
|
+
* Guessing a method name here would be the generic `add` that GTK4 deliberately removed.
|
|
135
119
|
*/
|
|
136
120
|
export declare function mountRoot(el: HostElement, container: GObject.Object): void;
|
|
137
121
|
/**
|
|
138
122
|
* The materialised widget of a host node — for a `ref`, or for a test.
|
|
139
123
|
*
|
|
140
|
-
* ONE implementation
|
|
141
|
-
*
|
|
142
|
-
* no supported way to reach a widget at all and its only route was
|
|
143
|
-
* `materialize()`, which is exactly the call the `destroyed` guard below exists to
|
|
144
|
-
* intercept.
|
|
124
|
+
* ONE implementation, because a caller reaching `materialize()` directly is exactly what the
|
|
125
|
+
* `destroyed` guard below exists to intercept.
|
|
145
126
|
*
|
|
146
|
-
* The flag is exact and the obvious heuristic is not: `materialize` would happily
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
127
|
+
* The flag is exact and the obvious heuristic is not: `materialize` would happily build a
|
|
128
|
+
* fresh, propertyless, unparented widget for a destroyed node — `destroy` clears `props`
|
|
129
|
+
* and `layout` precisely so one cannot look re-materialisable — and "no widget, not
|
|
130
|
+
* attached, no props" also describes a brand-new element.
|
|
150
131
|
*/
|
|
151
132
|
export declare function widgetOf(node: HostNode): Gtk.Widget;
|
|
152
133
|
/**
|
|
153
134
|
* An off-screen container the host owns — the analogue of the DOM's detached `<div>`.
|
|
154
135
|
*
|
|
155
|
-
* `<KeepAlive>` and `<Suspense>` ask a renderer for one: `KeepAliveImpl.setup`
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* `
|
|
159
|
-
* `
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* (`makeDetachedContainer`), and this op is what leaves the adapter with nothing to
|
|
166
|
-
* know: the deactivated subtree is really unparented from the visible tree and
|
|
167
|
-
* really held alive, so reactivating it moves the SAME widgets back.
|
|
136
|
+
* `<KeepAlive>` and `<Suspense>` ask a renderer for one: `KeepAliveImpl.setup` opens with
|
|
137
|
+
* `createElement("div")` and `SuspenseImpl` does the same for its `hiddenContainer`.
|
|
138
|
+
* Forwarded as a TAG, "div" reached `lookupWidget` and threw `unknown-tag` inside
|
|
139
|
+
* `callWithErrorHandling`, whose production arm is `console.error` with no rethrow:
|
|
140
|
+
* `mount()` returned normally, the container held zero children, GTK said nothing, exit 0.
|
|
141
|
+
*
|
|
142
|
+
* Which widget backs it is the table's business (`makeDetachedContainer`), and this op is
|
|
143
|
+
* what leaves the adapter with nothing to know — the widget knowledge ADR 0027 § 7 forbids.
|
|
144
|
+
* The deactivated subtree is really unparented from the visible tree and really held
|
|
145
|
+
* alive, so reactivating it moves the SAME widgets back.
|
|
168
146
|
*/
|
|
169
147
|
export declare const createDetachedContainer: () => HostElement;
|
|
170
148
|
/**
|