react-x11 1.2.0 → 2.0.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/README.md +330 -81
- package/package.json +132 -14
- package/src/ClickToComponent.js +9 -2
- package/src/DevToolsIntegration.js +440 -32
- package/src/Reconciler.js +463 -165
- package/src/a11y.js +1299 -0
- package/src/acceleratorhooks.js +86 -0
- package/src/accelerators.js +128 -0
- package/src/activate.js +168 -0
- package/src/anchor.js +360 -0
- package/src/appcontext.js +161 -0
- package/src/appearance.js +748 -0
- package/src/appearancehooks.js +96 -0
- package/src/apphooks.js +73 -0
- package/src/application.js +748 -0
- package/src/atspi.js +1953 -0
- package/src/bus.js +545 -0
- package/src/bushooks.js +136 -0
- package/src/clientmessage.js +140 -0
- package/src/clipboard.js +121 -0
- package/src/components/Button.js +148 -33
- package/src/components/Checkbox.js +66 -32
- package/src/components/Dialog.js +96 -29
- package/src/components/FileDialog.js +491 -0
- package/src/components/Icon.js +329 -0
- package/src/components/Menu.js +797 -133
- package/src/components/PasswordInput.js +434 -0
- package/src/components/ProgressBar.js +91 -12
- package/src/components/Radio.js +78 -35
- package/src/components/Select.js +255 -65
- package/src/components/Slider.js +102 -41
- package/src/components/SplitPane.js +206 -0
- package/src/components/Switch.js +100 -22
- package/src/components/Table.js +529 -0
- package/src/components/Tabs.js +211 -0
- package/src/components/Tooltip.js +528 -54
- package/src/components/anchor.js +154 -107
- package/src/components/change.js +34 -0
- package/src/components/dnd.js +103 -0
- package/src/components/index.js +16 -3
- package/src/components/keys.js +17 -20
- package/src/components/scribble.js +247 -0
- package/src/components/theme.js +350 -42
- package/src/components/typeahead.js +12 -2
- package/src/compose.js +868 -0
- package/src/compositing.js +224 -0
- package/src/dbusmenu.js +384 -0
- package/src/debug.d.ts +63 -0
- package/src/debug.js +642 -0
- package/src/decorations.js +486 -0
- package/src/desktopsettings.js +209 -0
- package/src/desktopsettingshooks.js +62 -0
- package/src/dnd.js +1725 -0
- package/src/editmenu.js +272 -0
- package/src/errors.js +98 -0
- package/src/events.js +1406 -162
- package/src/extensions.js +45 -0
- package/src/filedialog.js +375 -0
- package/src/filedialoghooks.js +132 -0
- package/src/fonthooks.js +64 -0
- package/src/fonts.js +301 -0
- package/src/foreignnodes.js +519 -0
- package/src/frame/child.js +33 -0
- package/src/frame/childmain.js +274 -0
- package/src/frame/env.js +140 -0
- package/src/frame/index.js +444 -0
- package/src/frame/lifecycle.js +67 -0
- package/src/frame/protocol.js +179 -0
- package/src/frames.js +73 -0
- package/src/glbackend.js +114 -0
- package/src/glnodes.js +125 -67
- package/src/globalmenu.js +683 -0
- package/src/host.d.ts +88 -0
- package/src/host.js +42 -0
- package/src/idle.js +490 -0
- package/src/idlehooks.js +100 -0
- package/src/imagesource.js +349 -0
- package/src/index.d.ts +475 -0
- package/src/index.js +83 -9
- package/src/inputtime.js +206 -0
- package/src/jsx-dev-runtime.d.ts +21 -0
- package/src/jsx-dev-runtime.js +2 -0
- package/src/jsx-runtime.d.ts +39 -0
- package/src/jsx-runtime.js +6 -0
- package/src/keyboard.js +256 -0
- package/src/keyboardstate.js +278 -0
- package/src/keyboardstatehooks.js +58 -0
- package/src/keysyms.d.ts +149 -0
- package/src/keysyms.js +270 -0
- package/src/locale.js +170 -0
- package/src/localehooks.js +47 -0
- package/src/menuitem.js +223 -0
- package/src/node.d.ts +597 -0
- package/src/node.js +44 -0
- package/src/nodes.js +9546 -690
- package/src/ntk.d.ts +44 -0
- package/src/ntk.js +25 -0
- package/src/paintcache.js +366 -0
- package/src/palette.js +380 -0
- package/src/pastestate.js +66 -0
- package/src/portal.js +461 -0
- package/src/priority.js +26 -0
- package/src/refresh/index.d.ts +40 -0
- package/src/refresh/index.js +122 -0
- package/src/refresh/loader.d.ts +37 -0
- package/src/refresh/loader.js +401 -0
- package/src/refresh/register.d.ts +5 -0
- package/src/refresh/register.js +13 -0
- package/src/registry.js +232 -0
- package/src/scale.js +626 -0
- package/src/scalehooks.js +27 -0
- package/src/screencolor.js +640 -0
- package/src/screencolorhooks.js +101 -0
- package/src/screens.js +754 -0
- package/src/screenshooks.js +137 -0
- package/src/startup.js +302 -0
- package/src/style.d.ts +126 -0
- package/src/style.js +33 -0
- package/src/styles.js +1482 -6
- package/src/svgnodes.js +306 -0
- package/src/testing/a11y.js +484 -0
- package/src/testing/components.js +414 -0
- package/src/testing/events.js +407 -0
- package/src/testing/harness.js +455 -0
- package/src/testing/index.d.ts +558 -0
- package/src/testing/index.js +85 -0
- package/src/testing/mock-app.js +463 -0
- package/src/testing/pixels.js +152 -0
- package/src/testing/queries.js +224 -0
- package/src/textrange.js +83 -0
- package/src/textselection.js +439 -0
- package/src/trace-registry.js +63 -0
- package/src/transfer.js +93 -0
- package/src/types/appearance.d.ts +84 -0
- package/src/types/application.d.ts +173 -0
- package/src/types/components.d.ts +820 -0
- package/src/types/dbus.d.ts +177 -0
- package/src/types/elements.d.ts +897 -0
- package/src/types/events.d.ts +549 -0
- package/src/types/filedialog.d.ts +260 -0
- package/src/types/fonts.d.ts +124 -0
- package/src/types/frame.d.ts +146 -0
- package/src/types/globalmenu.d.ts +42 -0
- package/src/types/nodes.d.ts +199 -0
- package/src/types/screencolor.d.ts +84 -0
- package/src/types/style.d.ts +434 -0
- package/src/types/system.d.ts +287 -0
- package/src/windowid.js +151 -0
- package/src/windowstate.js +393 -0
- package/src/xsettings.js +336 -0
- package/src/yoga.d.ts +55 -0
- package/src/yoga.js +135 -0
- package/src/components/Canvas3D.js +0 -28
- package/src/geometry3d.js +0 -223
- package/src/pointer3d.js +0 -158
- package/src/raycast3d.js +0 -146
- package/src/richnodes.js +0 -436
- package/src/scene3d.js +0 -683
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synthetic events. Dispatched capture → target → bubble over the drawn
|
|
3
|
+
* tree by front-to-back hit testing, the same shape React gives you in the
|
|
4
|
+
* DOM. See docs/events.md.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { RefObject } from 'react';
|
|
8
|
+
import type { DrawnNode, NtkWindow, TextInputNode } from './nodes.js';
|
|
9
|
+
import type { MenuShortcut } from './components.js';
|
|
10
|
+
|
|
11
|
+
/** The raw ntk/X11 event a synthetic one was made from. */
|
|
12
|
+
export interface NativeEvent {
|
|
13
|
+
/** X event type number. */
|
|
14
|
+
type: number;
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Window-relative pointer position. */
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
/** Screen coordinates — what you anchor a `<popup>` at. */
|
|
20
|
+
rootx: number;
|
|
21
|
+
rooty: number;
|
|
22
|
+
/** X modifier/button mask. */
|
|
23
|
+
buttons: number;
|
|
24
|
+
keycode?: number;
|
|
25
|
+
codepoint?: number;
|
|
26
|
+
time?: number;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SyntheticEvent<T = DrawnNode> {
|
|
31
|
+
type: string;
|
|
32
|
+
/** The node the event was dispatched at (the public instance). */
|
|
33
|
+
target: T;
|
|
34
|
+
/** The node whose handler is running. */
|
|
35
|
+
currentTarget: T | null;
|
|
36
|
+
/** Window coordinates. */
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
/** Coordinates relative to `target`'s box. */
|
|
40
|
+
localX: number;
|
|
41
|
+
localY: number;
|
|
42
|
+
nativeEvent: NativeEvent;
|
|
43
|
+
shiftKey: boolean;
|
|
44
|
+
ctrlKey: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* X11 Mod1 — Alt on virtually every keymap, but a convention rather than
|
|
47
|
+
* a rule of the protocol. `nativeEvent.buttons` has the raw mask for a
|
|
48
|
+
* setup that remaps it.
|
|
49
|
+
*/
|
|
50
|
+
altKey: boolean;
|
|
51
|
+
/** X11 Mod4 — Super, under the DOM's name for it. Same caveat as `altKey`. */
|
|
52
|
+
metaKey: boolean;
|
|
53
|
+
defaultPrevented: boolean;
|
|
54
|
+
propagationStopped: boolean;
|
|
55
|
+
/** Suppress the element's built-in behaviour (editing, wheel scrolling…). */
|
|
56
|
+
preventDefault(): void;
|
|
57
|
+
stopPropagation(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Route the rest of this gesture's `mousemove`/`mouseup` to this node even
|
|
60
|
+
* once the pointer leaves it. Released on mouseup and on unmount.
|
|
61
|
+
*/
|
|
62
|
+
capturePointer(): void;
|
|
63
|
+
releasePointer(): void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface MouseEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
67
|
+
/** X button number: 1 left, 2 middle, 3 right. */
|
|
68
|
+
button: number;
|
|
69
|
+
/** DOM-style click count — 2 is a double click, 3 a triple. */
|
|
70
|
+
detail: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The pointer looks like it is heading here (ntk#37) — said *before* it
|
|
75
|
+
* arrives, so there is time to do something about it.
|
|
76
|
+
*
|
|
77
|
+
* Not routed like the other pointer events. Nothing is hit tested and there
|
|
78
|
+
* is no capture or bubble phase: nodes that want attention register
|
|
79
|
+
* themselves, the pointer's trajectory is matched against their rectangles,
|
|
80
|
+
* and the one it would enter soonest is the one that hears about it. Only one
|
|
81
|
+
* node in a window holds attention at a time.
|
|
82
|
+
*/
|
|
83
|
+
export interface AttentionEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
84
|
+
/**
|
|
85
|
+
* Roughly how many milliseconds until the pointer arrives, at the speed it
|
|
86
|
+
* is currently travelling — 0 when it is already inside.
|
|
87
|
+
*
|
|
88
|
+
* This is the number worth branching on. "The pointer is here in 30ms" and
|
|
89
|
+
* "in 220ms" justify very different amounts of speculative work, and the
|
|
90
|
+
* renderer is the only party that knows which one this is.
|
|
91
|
+
*/
|
|
92
|
+
eta: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface WheelEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
96
|
+
/** Pixels, positive right — one notch of the wheel is 48 of them. */
|
|
97
|
+
deltaX: number;
|
|
98
|
+
/** Pixels, positive down. Fractions of a notch where `smooth`. */
|
|
99
|
+
deltaY: number;
|
|
100
|
+
/**
|
|
101
|
+
* Whether the device measured this scroll rather than clicked it: XI2's
|
|
102
|
+
* scroll valuators (a touchpad, a high-resolution wheel) can report a
|
|
103
|
+
* fraction of a notch, the emulated buttons 4-7 can only ever say one.
|
|
104
|
+
*/
|
|
105
|
+
smooth: boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface KeyboardEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
109
|
+
/** X keycode. */
|
|
110
|
+
keycode: number;
|
|
111
|
+
/**
|
|
112
|
+
* X keysym (`XK_*`), or undefined if the map has no entry — **the Latin
|
|
113
|
+
* one**, so a shortcut keeps matching while another layout is typing.
|
|
114
|
+
* `ev.key`/`ev.codepoint` are what the key produced; this is what it is
|
|
115
|
+
* called. See "Layouts" in docs/events.md, and
|
|
116
|
+
* `createRoot({ accelerators })` to turn the resolution off.
|
|
117
|
+
*/
|
|
118
|
+
keysym?: number;
|
|
119
|
+
/** Which XKB layout group typed this, 0-3. A layout switch moves the
|
|
120
|
+
* group and sends no other notice. */
|
|
121
|
+
group: number;
|
|
122
|
+
/** Unicode code point, undefined when the key produces no character —
|
|
123
|
+
* which includes every key a composition took (see `composing`). */
|
|
124
|
+
codepoint?: number;
|
|
125
|
+
/** The character the key produced, undefined for non-printing keys and
|
|
126
|
+
* for keys a composition took. */
|
|
127
|
+
key?: string;
|
|
128
|
+
/** Whether this key belongs to an open composition — a dead key, or a key
|
|
129
|
+
* of a Compose sequence. Its text arrives on the composition events
|
|
130
|
+
* instead, so a handler that types from `onKeyDown` should skip it. */
|
|
131
|
+
composing: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* A composition — text the user is still typing. `onCompositionStart` has
|
|
136
|
+
* no data, `onCompositionUpdate` carries what is showing at the caret, and
|
|
137
|
+
* `onCompositionEnd` carries the text that was committed (empty when the
|
|
138
|
+
* sequence was abandoned).
|
|
139
|
+
*/
|
|
140
|
+
export interface CompositionEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
141
|
+
data: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface FocusEvent<T = DrawnNode> extends SyntheticEvent<T> {}
|
|
145
|
+
|
|
146
|
+
/** What a drop target's `dropAccept` prop takes: an exact type name
|
|
147
|
+
* (`'image/png'`), a semantic group (`'files' | 'uris' | 'text'`), an
|
|
148
|
+
* array of either, or a predicate over the offered names. Absent means
|
|
149
|
+
* the node accepts anything — a bare `onDrop` is a valid dropzone. */
|
|
150
|
+
export type DropAccept = string | string[] | ((types: string[]) => boolean);
|
|
151
|
+
|
|
152
|
+
export type DropAction = 'copy' | 'move' | 'link' | 'ask' | 'private';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* A drag over a drop target (`onDragEnter` / `onDragOver` /
|
|
156
|
+
* `onDragLeave`). Enter/leave do not bubble, like their mouse
|
|
157
|
+
* counterparts; `onDragOver` dispatches capture → target → bubble.
|
|
158
|
+
*/
|
|
159
|
+
export interface DragEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
160
|
+
/** Offered payload type names, e.g. `['text/uri-list', 'text/plain']`. */
|
|
161
|
+
types: string[];
|
|
162
|
+
/** Alias-aware membership test: a concrete type or a semantic group. */
|
|
163
|
+
has(type: string): boolean;
|
|
164
|
+
/** The action the source asked for. `'ask'` means it wants the user
|
|
165
|
+
* offered a choice — see `actions`. */
|
|
166
|
+
action: DropAction;
|
|
167
|
+
/** The actions an `'ask'` source will accept, in the order it listed
|
|
168
|
+
* them. Empty for every other action, which is all but a few file
|
|
169
|
+
* managers. */
|
|
170
|
+
actions: Array<'copy' | 'move' | 'link'>;
|
|
171
|
+
/** The source's own words for `actions`, positionally matched, with
|
|
172
|
+
* `null` where it offered none. Empty when `actions` is. */
|
|
173
|
+
actionDescriptions: Array<string | null>;
|
|
174
|
+
/** Where the drag came from: another application, or this one. */
|
|
175
|
+
source: 'internal' | 'external';
|
|
176
|
+
/** Pointer position in screen (root) coordinates. */
|
|
177
|
+
screenX: number;
|
|
178
|
+
screenY: number;
|
|
179
|
+
/** Override the declarative `dropAccept` answer for this position
|
|
180
|
+
* (`onDragOver`), or settle what the drop actually did (`onDrop`, where
|
|
181
|
+
* `accept` picks the action reported to the source and `reject` tells it
|
|
182
|
+
* the drop was not taken after all). Inert elsewhere. */
|
|
183
|
+
accept(action?: 'copy' | 'move' | 'link'): void;
|
|
184
|
+
reject(): void;
|
|
185
|
+
/** Opt into the XdndStatus suppression rectangle for this node's rect:
|
|
186
|
+
* the source stops sending positions while the pointer stays inside.
|
|
187
|
+
* Do not freeze a zone that draws per-position feedback (insertion
|
|
188
|
+
* carets, edge auto-scroll). */
|
|
189
|
+
freeze(): void;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The drop itself (`onDrop`). The common payloads are prefetched —
|
|
193
|
+
* `files` and `text` read synchronously; everything else is behind
|
|
194
|
+
* `getData`. There is deliberately no `dataTransfer`: X selection
|
|
195
|
+
* transfer is asynchronous, and a sync-looking `getData` would return
|
|
196
|
+
* `"[object Promise]"` silently. */
|
|
197
|
+
export interface DropEvent<T = DrawnNode> extends DragEvent<T> {
|
|
198
|
+
/** One conversion of the drag payload. Text-ish targets decode to a
|
|
199
|
+
* string; anything else stays raw bytes. Semantic groups resolve to
|
|
200
|
+
* the first concretely offered member. */
|
|
201
|
+
getData(type: string): Promise<Uint8Array | string>;
|
|
202
|
+
/** Parsed `text/uri-list` (RFC 2483). `path` is present only for
|
|
203
|
+
* genuinely local `file:` URIs. Empty when no file flavour was
|
|
204
|
+
* offered. */
|
|
205
|
+
files: Array<{ uri: string; path?: string }>;
|
|
206
|
+
/** The best offered text flavour, when there was one. */
|
|
207
|
+
text?: string;
|
|
208
|
+
/** Internal drags only: the dragData values by type name, live — no
|
|
209
|
+
* serialisation happened. Absent for drops from other applications. */
|
|
210
|
+
items?: Record<string, unknown>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** A drag *source*'s events (`onDragStart` / `onDrag` / `onDragEnd`).
|
|
214
|
+
* `source` and `accepted` describe the transport and the current target's
|
|
215
|
+
* answer; `screenX/screenY` are where the pointer is, in root coordinates
|
|
216
|
+
* — what a preview `<popup>` follows. */
|
|
217
|
+
export interface DragSourceEvent<T = DrawnNode> extends SyntheticEvent<T> {
|
|
218
|
+
types: string[];
|
|
219
|
+
action: DropAction;
|
|
220
|
+
source: 'internal' | 'external';
|
|
221
|
+
screenX: number;
|
|
222
|
+
screenY: number;
|
|
223
|
+
/** Whether whatever is under the pointer currently accepts the drop. */
|
|
224
|
+
accepted?: boolean;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** `onDragEnd`: `action` is what the drop performed, or null when the drag
|
|
228
|
+
* ended nowhere (or was rejected). */
|
|
229
|
+
export interface DragEndEvent<T = DrawnNode> extends Omit<
|
|
230
|
+
DragSourceEvent<T>,
|
|
231
|
+
'action'
|
|
232
|
+
> {
|
|
233
|
+
action: DropAction | null;
|
|
234
|
+
dropped: boolean;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* The props that make a node draggable. `dragData` maps payload type names
|
|
239
|
+
* to values: strings and bytes are served as-is, thunks are resolved
|
|
240
|
+
* lazily (at delivery for an in-app drop, at promotion for an external
|
|
241
|
+
* one), and any other live value reaches in-app drops by reference
|
|
242
|
+
* (`e.items`) but is JSON-serialised for the wire.
|
|
243
|
+
*/
|
|
244
|
+
export interface DragSourceProps<T = DrawnNode> {
|
|
245
|
+
draggable?: boolean;
|
|
246
|
+
dragData?: Record<
|
|
247
|
+
string,
|
|
248
|
+
string | Uint8Array | (() => string | Uint8Array | unknown) | unknown
|
|
249
|
+
>;
|
|
250
|
+
/** Offered actions, preferred first. Defaults to `['copy']`. */
|
|
251
|
+
dragActions?: Array<'copy' | 'move' | 'link'>;
|
|
252
|
+
/** Fires past the drag threshold; `preventDefault()` cancels the drag
|
|
253
|
+
* (the gesture continues as plain mouse events). */
|
|
254
|
+
onDragStart?: (ev: DragSourceEvent<T>) => void;
|
|
255
|
+
/** Per motion while dragging — the source-side mirror of onDragOver. */
|
|
256
|
+
onDrag?: (ev: DragSourceEvent<T>) => void;
|
|
257
|
+
onDragEnd?: (ev: DragEndEvent<T>) => void;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** The props that make a node a drop target. Any drawn element and
|
|
261
|
+
* `<window>`/`<popup>` accept them; their presence registers the node
|
|
262
|
+
* with the XDND router (see docs/events.md). */
|
|
263
|
+
export interface DropTargetProps<T = DrawnNode> {
|
|
264
|
+
dropAccept?: DropAccept;
|
|
265
|
+
/** Does not propagate — synthesized by drag-path diffing, and paired
|
|
266
|
+
* with the `':drag-over'` style state. */
|
|
267
|
+
onDragEnter?: (ev: DragEvent<T>) => void;
|
|
268
|
+
onDragLeave?: (ev: DragEvent<T>) => void;
|
|
269
|
+
onDragOver?: (ev: DragEvent<T>) => void;
|
|
270
|
+
onDragOverCapture?: (ev: DragEvent<T>) => void;
|
|
271
|
+
/** May be async: XdndFinished is held until the returned promise
|
|
272
|
+
* settles (or a ~10 s watchdog fires, so a forgotten await cannot hang
|
|
273
|
+
* the source application's gesture). */
|
|
274
|
+
onDrop?: (ev: DropEvent<T>) => void | Promise<void>;
|
|
275
|
+
onDropCapture?: (ev: DropEvent<T>) => void | Promise<void>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* `<textinput onChange>` / `<textarea onChange>`. The value is on both
|
|
280
|
+
* `ev.value` and `ev.target.value` — the second is what every DOM form
|
|
281
|
+
* library reads, and it is the *new* value even in controlled mode, where
|
|
282
|
+
* `props.value` is still the old string until the parent re-renders.
|
|
283
|
+
*
|
|
284
|
+
* `nativeEvent` is the X key event when a keystroke drove the edit, and null
|
|
285
|
+
* when nothing did — a paste resolving, an undo, a value the parent pushed
|
|
286
|
+
* back. Guard it.
|
|
287
|
+
*/
|
|
288
|
+
/**
|
|
289
|
+
* The document selection in a `selectable` element changed — a drag, a
|
|
290
|
+
* double click, Ctrl+A, or a `selectAll()` from code. Not a pointer event:
|
|
291
|
+
* it reports state, and the gesture that moved it has already been
|
|
292
|
+
* dispatched as one.
|
|
293
|
+
*/
|
|
294
|
+
export interface SelectionChangeEvent<T = DrawnNode> {
|
|
295
|
+
type: 'selectionChange';
|
|
296
|
+
target: T;
|
|
297
|
+
currentTarget: T;
|
|
298
|
+
/** The selected text, assembled the way a copy would assemble it. */
|
|
299
|
+
text: string;
|
|
300
|
+
isCollapsed: boolean;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export interface ChangeEvent<T = TextInputNode> extends Omit<
|
|
304
|
+
SyntheticEvent<T>,
|
|
305
|
+
'nativeEvent'
|
|
306
|
+
> {
|
|
307
|
+
type: 'change';
|
|
308
|
+
value: string;
|
|
309
|
+
/** The control's `name` prop, mirrored from `target.name`. */
|
|
310
|
+
name?: string;
|
|
311
|
+
nativeEvent: NativeEvent | null;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* `<textinput onSubmit>` — Enter, or Ctrl+Enter in a `<textarea>`. Same
|
|
316
|
+
* shape as {@link ChangeEvent}; `nativeEvent` is the X key event.
|
|
317
|
+
*/
|
|
318
|
+
export interface SubmitEvent<T = TextInputNode> extends Omit<
|
|
319
|
+
ChangeEvent<T>,
|
|
320
|
+
'type'
|
|
321
|
+
> {
|
|
322
|
+
type: 'submit';
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** `<box onScroll>` — a scrolling box or window moved. */
|
|
326
|
+
export interface ScrollEvent {
|
|
327
|
+
scrollX: number;
|
|
328
|
+
scrollY: number;
|
|
329
|
+
contentWidth: number;
|
|
330
|
+
contentHeight: number;
|
|
331
|
+
viewportWidth: number;
|
|
332
|
+
viewportHeight: number;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** `<box onViewport>` — fired from layout, not from scrolling. */
|
|
336
|
+
export interface ViewportEvent {
|
|
337
|
+
width: number;
|
|
338
|
+
height: number;
|
|
339
|
+
contentWidth: number;
|
|
340
|
+
contentHeight: number;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Handlers every drawn element and `<window>` accepts. */
|
|
344
|
+
export interface PointerHandlers<T = DrawnNode> {
|
|
345
|
+
onClick?: (ev: MouseEvent<T>) => void;
|
|
346
|
+
onClickCapture?: (ev: MouseEvent<T>) => void;
|
|
347
|
+
onMouseDown?: (ev: MouseEvent<T>) => void;
|
|
348
|
+
onMouseDownCapture?: (ev: MouseEvent<T>) => void;
|
|
349
|
+
onMouseUp?: (ev: MouseEvent<T>) => void;
|
|
350
|
+
onMouseUpCapture?: (ev: MouseEvent<T>) => void;
|
|
351
|
+
onMouseMove?: (ev: MouseEvent<T>) => void;
|
|
352
|
+
onMouseMoveCapture?: (ev: MouseEvent<T>) => void;
|
|
353
|
+
/** Does not propagate — synthesized by hover-path diffing. */
|
|
354
|
+
onMouseEnter?: (ev: MouseEvent<T>) => void;
|
|
355
|
+
onMouseLeave?: (ev: MouseEvent<T>) => void;
|
|
356
|
+
/**
|
|
357
|
+
* **Provisional — the `unstable_` prefix is the contract.** A prototype for
|
|
358
|
+
* ntk#37, kept out of `docs/` on purpose: the shape may change or be
|
|
359
|
+
* withdrawn, and dropping the prefix is what would say it had settled.
|
|
360
|
+
*
|
|
361
|
+
* The pointer is heading for this node and has not arrived. For starting
|
|
362
|
+
* work early — warming a cache, decoding an image, sending the query whose
|
|
363
|
+
* answer the click will want.
|
|
364
|
+
*
|
|
365
|
+
* Fires on arrival of attention only. There is no matching "lost" event:
|
|
366
|
+
* work started on a hint does not want undoing because the pointer changed
|
|
367
|
+
* its mind, and anything *visual* belongs in an `:attention` style block,
|
|
368
|
+
* which is cleared automatically. Declaring either one registers the node
|
|
369
|
+
* as a candidate; a tree that declares neither costs nothing per motion
|
|
370
|
+
* event.
|
|
371
|
+
*
|
|
372
|
+
* Does not propagate, and unlike `onMouseEnter` it is not the hover path
|
|
373
|
+
* either — see `AttentionEvent`.
|
|
374
|
+
*/
|
|
375
|
+
unstable_onAttention?: (ev: AttentionEvent<T>) => void;
|
|
376
|
+
onWheel?: (ev: WheelEvent<T>) => void;
|
|
377
|
+
onWheelCapture?: (ev: WheelEvent<T>) => void;
|
|
378
|
+
/**
|
|
379
|
+
* Right-click (button 3), dispatched after `onMouseDown` — so suppressing
|
|
380
|
+
* the menu does not also give up whatever mousedown did. `preventDefault()`
|
|
381
|
+
* skips the element's own menu, which today means the edit menu on
|
|
382
|
+
* `<textinput>` and `<textarea>`.
|
|
383
|
+
*/
|
|
384
|
+
onContextMenu?: (ev: MouseEvent<T>) => void;
|
|
385
|
+
onContextMenuCapture?: (ev: MouseEvent<T>) => void;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export interface KeyboardHandlers<T = DrawnNode> {
|
|
389
|
+
onKeyDown?: (ev: KeyboardEvent<T>) => void;
|
|
390
|
+
onKeyDownCapture?: (ev: KeyboardEvent<T>) => void;
|
|
391
|
+
onKeyUp?: (ev: KeyboardEvent<T>) => void;
|
|
392
|
+
onKeyUpCapture?: (ev: KeyboardEvent<T>) => void;
|
|
393
|
+
/**
|
|
394
|
+
* A composition opened — a dead key was pressed, or the Compose key was.
|
|
395
|
+
* `preventDefault()` on any of the three stops the element acting on it,
|
|
396
|
+
* which for `<textinput>` means showing or committing the text.
|
|
397
|
+
*/
|
|
398
|
+
onCompositionStart?: (ev: CompositionEvent<T>) => void;
|
|
399
|
+
onCompositionStartCapture?: (ev: CompositionEvent<T>) => void;
|
|
400
|
+
/** The composition changed: `data` is what is showing at the caret. */
|
|
401
|
+
onCompositionUpdate?: (ev: CompositionEvent<T>) => void;
|
|
402
|
+
onCompositionUpdateCapture?: (ev: CompositionEvent<T>) => void;
|
|
403
|
+
/** The composition finished: `data` is the text it produced, empty if it
|
|
404
|
+
* was abandoned. */
|
|
405
|
+
onCompositionEnd?: (ev: CompositionEvent<T>) => void;
|
|
406
|
+
onCompositionEndCapture?: (ev: CompositionEvent<T>) => void;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface FocusHandlers<T = DrawnNode> {
|
|
410
|
+
onFocus?: (ev: FocusEvent<T>) => void;
|
|
411
|
+
onBlur?: (ev: FocusEvent<T>) => void;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export interface EventHandlers<T = DrawnNode>
|
|
415
|
+
extends
|
|
416
|
+
PointerHandlers<T>,
|
|
417
|
+
KeyboardHandlers<T>,
|
|
418
|
+
FocusHandlers<T>,
|
|
419
|
+
DropTargetProps<T>,
|
|
420
|
+
DragSourceProps<T> {}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* `<window onResize>`: X's ConfigureNotify, handed over as ntk's own event
|
|
424
|
+
* object rather than a synthetic one — there is no capture/bubble phase and
|
|
425
|
+
* nothing to `preventDefault`, because the window manager has already done
|
|
426
|
+
* the thing being reported.
|
|
427
|
+
*
|
|
428
|
+
* It fires for **moves and reparents** as much as for size changes; see
|
|
429
|
+
* docs/elements.md. `x`/`y` are relative to whatever the window's parent is,
|
|
430
|
+
* which is the window manager's frame once it has framed the window — not
|
|
431
|
+
* screen coordinates.
|
|
432
|
+
*/
|
|
433
|
+
export interface WindowResizeEvent {
|
|
434
|
+
/** X event type number (22, ConfigureNotify). */
|
|
435
|
+
type: number;
|
|
436
|
+
x: number;
|
|
437
|
+
y: number;
|
|
438
|
+
width: number;
|
|
439
|
+
height: number;
|
|
440
|
+
/** The size differs from the last delivered event's. */
|
|
441
|
+
resized: boolean;
|
|
442
|
+
/** The position does. */
|
|
443
|
+
moved: boolean;
|
|
444
|
+
/**
|
|
445
|
+
* The geometry `moved`/`resized` are measured against, or null when none
|
|
446
|
+
* is known yet.
|
|
447
|
+
*/
|
|
448
|
+
previous: { x: number; y: number; width: number; height: number } | null;
|
|
449
|
+
/** Every raw event merged into this one, oldest first. */
|
|
450
|
+
coalesced?: WindowResizeEvent[];
|
|
451
|
+
window: NtkWindow;
|
|
452
|
+
target: NtkWindow;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* `<window onClientMessage>`: a ClientMessage addressed to this window —
|
|
457
|
+
* EWMH, XEmbed, the system tray, or a convention two copies of one
|
|
458
|
+
* application agreed between themselves.
|
|
459
|
+
*
|
|
460
|
+
* Not a synthetic event: a ClientMessage is addressed to a *window*, so
|
|
461
|
+
* there is no node under it, nothing to hit test and no chain to bubble
|
|
462
|
+
* along. Delivered in arrival order, which the chunked protocols depend on.
|
|
463
|
+
*/
|
|
464
|
+
export interface ClientMessageEvent {
|
|
465
|
+
/** X event type number (33, ClientMessage). */
|
|
466
|
+
type: number;
|
|
467
|
+
/**
|
|
468
|
+
* The message type atom's **name** — `'_NET_SYSTEM_TRAY_OPCODE'`,
|
|
469
|
+
* `'_XEMBED'`, `'WM_PROTOCOLS'` — which is what a handler branches on.
|
|
470
|
+
*
|
|
471
|
+
* `null` for an atom this connection has never named. An application
|
|
472
|
+
* acting on a protocol has interned its atoms already, so that is the
|
|
473
|
+
* passive-observer case rather than a coin flip; {@link atom} is exact
|
|
474
|
+
* either way.
|
|
475
|
+
*/
|
|
476
|
+
messageType: string | null;
|
|
477
|
+
/** The message type atom id, as it arrived. */
|
|
478
|
+
atom: number;
|
|
479
|
+
/** How wide the 20 payload bytes are read. */
|
|
480
|
+
format: 8 | 16 | 32;
|
|
481
|
+
/** 5 values at format 32, 10 at 16, 20 at 8. */
|
|
482
|
+
data: number[];
|
|
483
|
+
/** The window it was delivered to. */
|
|
484
|
+
window: NtkWindow;
|
|
485
|
+
target: NtkWindow;
|
|
486
|
+
/** ntk's raw event. */
|
|
487
|
+
nativeEvent: unknown;
|
|
488
|
+
defaultPrevented: boolean;
|
|
489
|
+
/**
|
|
490
|
+
* Stop react-x11 acting on this message itself — which today means XDND,
|
|
491
|
+
* for a window answering the drag protocol on its own terms. It does not
|
|
492
|
+
* reach the WM close button; `onCloseRequest` is that seam.
|
|
493
|
+
*/
|
|
494
|
+
preventDefault(): void;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// --------------------------------------------------------------------------
|
|
498
|
+
// Accelerators
|
|
499
|
+
// --------------------------------------------------------------------------
|
|
500
|
+
|
|
501
|
+
export interface AcceleratorOptions {
|
|
502
|
+
/** `false` unbinds the chord without unmounting anything. Defaults true. */
|
|
503
|
+
enabled?: boolean;
|
|
504
|
+
/**
|
|
505
|
+
* The node the binding hangs off, deciding what it is hidden with and what
|
|
506
|
+
* a modal `<popup>` takes it away from. Defaults to the window the
|
|
507
|
+
* component is in, which is what an application-wide shortcut wants; pass
|
|
508
|
+
* a node inside a modal `<Dialog>` to give the dialog a shortcut of its
|
|
509
|
+
* own.
|
|
510
|
+
*/
|
|
511
|
+
scope?: RefObject<DrawnNode | null>;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* A shortcut that is not in a menu, on the same chord vocabulary a menu
|
|
516
|
+
* item's `shortcut` uses — so one can be moved into or out of a menu
|
|
517
|
+
* without being rewritten.
|
|
518
|
+
*
|
|
519
|
+
* ```tsx
|
|
520
|
+
* useAccelerator([['Control', 'K']], () => openPalette());
|
|
521
|
+
* ```
|
|
522
|
+
*
|
|
523
|
+
* Exact on Control/Alt/Shift/Super, indifferent to Caps Lock and Num Lock,
|
|
524
|
+
* matched against the Latin keysym so a layout switch does not turn it off,
|
|
525
|
+
* and behind whatever a focused element consumed with `preventDefault()`.
|
|
526
|
+
* See docs/events.md.
|
|
527
|
+
*/
|
|
528
|
+
export function useAccelerator(
|
|
529
|
+
shortcut: MenuShortcut,
|
|
530
|
+
handler: (ev: KeyboardEvent) => void,
|
|
531
|
+
options?: AcceleratorOptions,
|
|
532
|
+
): void;
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Whether a key event presses any alternative of a `shortcut` — the matcher
|
|
536
|
+
* the menus and {@link useAccelerator} both run on, for an application
|
|
537
|
+
* dispatching chords its own way.
|
|
538
|
+
*/
|
|
539
|
+
export function matchesShortcut(
|
|
540
|
+
ev: {
|
|
541
|
+
keysym?: number | null;
|
|
542
|
+
codepoint?: number | null;
|
|
543
|
+
ctrlKey?: boolean;
|
|
544
|
+
altKey?: boolean;
|
|
545
|
+
shiftKey?: boolean;
|
|
546
|
+
metaKey?: boolean;
|
|
547
|
+
},
|
|
548
|
+
shortcut: MenuShortcut | undefined,
|
|
549
|
+
): boolean;
|