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.
Files changed (158) hide show
  1. package/README.md +330 -81
  2. package/package.json +132 -14
  3. package/src/ClickToComponent.js +9 -2
  4. package/src/DevToolsIntegration.js +440 -32
  5. package/src/Reconciler.js +463 -165
  6. package/src/a11y.js +1299 -0
  7. package/src/acceleratorhooks.js +86 -0
  8. package/src/accelerators.js +128 -0
  9. package/src/activate.js +168 -0
  10. package/src/anchor.js +360 -0
  11. package/src/appcontext.js +161 -0
  12. package/src/appearance.js +748 -0
  13. package/src/appearancehooks.js +96 -0
  14. package/src/apphooks.js +73 -0
  15. package/src/application.js +748 -0
  16. package/src/atspi.js +1953 -0
  17. package/src/bus.js +545 -0
  18. package/src/bushooks.js +136 -0
  19. package/src/clientmessage.js +140 -0
  20. package/src/clipboard.js +121 -0
  21. package/src/components/Button.js +148 -33
  22. package/src/components/Checkbox.js +66 -32
  23. package/src/components/Dialog.js +96 -29
  24. package/src/components/FileDialog.js +491 -0
  25. package/src/components/Icon.js +329 -0
  26. package/src/components/Menu.js +797 -133
  27. package/src/components/PasswordInput.js +434 -0
  28. package/src/components/ProgressBar.js +91 -12
  29. package/src/components/Radio.js +78 -35
  30. package/src/components/Select.js +255 -65
  31. package/src/components/Slider.js +102 -41
  32. package/src/components/SplitPane.js +206 -0
  33. package/src/components/Switch.js +100 -22
  34. package/src/components/Table.js +529 -0
  35. package/src/components/Tabs.js +211 -0
  36. package/src/components/Tooltip.js +528 -54
  37. package/src/components/anchor.js +154 -107
  38. package/src/components/change.js +34 -0
  39. package/src/components/dnd.js +103 -0
  40. package/src/components/index.js +16 -3
  41. package/src/components/keys.js +17 -20
  42. package/src/components/scribble.js +247 -0
  43. package/src/components/theme.js +350 -42
  44. package/src/components/typeahead.js +12 -2
  45. package/src/compose.js +868 -0
  46. package/src/compositing.js +224 -0
  47. package/src/dbusmenu.js +384 -0
  48. package/src/debug.d.ts +63 -0
  49. package/src/debug.js +642 -0
  50. package/src/decorations.js +486 -0
  51. package/src/desktopsettings.js +209 -0
  52. package/src/desktopsettingshooks.js +62 -0
  53. package/src/dnd.js +1725 -0
  54. package/src/editmenu.js +272 -0
  55. package/src/errors.js +98 -0
  56. package/src/events.js +1406 -162
  57. package/src/extensions.js +45 -0
  58. package/src/filedialog.js +375 -0
  59. package/src/filedialoghooks.js +132 -0
  60. package/src/fonthooks.js +64 -0
  61. package/src/fonts.js +301 -0
  62. package/src/foreignnodes.js +519 -0
  63. package/src/frame/child.js +33 -0
  64. package/src/frame/childmain.js +274 -0
  65. package/src/frame/env.js +140 -0
  66. package/src/frame/index.js +444 -0
  67. package/src/frame/lifecycle.js +67 -0
  68. package/src/frame/protocol.js +179 -0
  69. package/src/frames.js +73 -0
  70. package/src/glbackend.js +114 -0
  71. package/src/glnodes.js +125 -67
  72. package/src/globalmenu.js +683 -0
  73. package/src/host.d.ts +88 -0
  74. package/src/host.js +42 -0
  75. package/src/idle.js +490 -0
  76. package/src/idlehooks.js +100 -0
  77. package/src/imagesource.js +349 -0
  78. package/src/index.d.ts +475 -0
  79. package/src/index.js +83 -9
  80. package/src/inputtime.js +206 -0
  81. package/src/jsx-dev-runtime.d.ts +21 -0
  82. package/src/jsx-dev-runtime.js +2 -0
  83. package/src/jsx-runtime.d.ts +39 -0
  84. package/src/jsx-runtime.js +6 -0
  85. package/src/keyboard.js +256 -0
  86. package/src/keyboardstate.js +278 -0
  87. package/src/keyboardstatehooks.js +58 -0
  88. package/src/keysyms.d.ts +149 -0
  89. package/src/keysyms.js +270 -0
  90. package/src/locale.js +170 -0
  91. package/src/localehooks.js +47 -0
  92. package/src/menuitem.js +223 -0
  93. package/src/node.d.ts +597 -0
  94. package/src/node.js +44 -0
  95. package/src/nodes.js +9546 -690
  96. package/src/ntk.d.ts +44 -0
  97. package/src/ntk.js +25 -0
  98. package/src/paintcache.js +366 -0
  99. package/src/palette.js +380 -0
  100. package/src/pastestate.js +66 -0
  101. package/src/portal.js +461 -0
  102. package/src/priority.js +26 -0
  103. package/src/refresh/index.d.ts +40 -0
  104. package/src/refresh/index.js +122 -0
  105. package/src/refresh/loader.d.ts +37 -0
  106. package/src/refresh/loader.js +401 -0
  107. package/src/refresh/register.d.ts +5 -0
  108. package/src/refresh/register.js +13 -0
  109. package/src/registry.js +232 -0
  110. package/src/scale.js +626 -0
  111. package/src/scalehooks.js +27 -0
  112. package/src/screencolor.js +640 -0
  113. package/src/screencolorhooks.js +101 -0
  114. package/src/screens.js +754 -0
  115. package/src/screenshooks.js +137 -0
  116. package/src/startup.js +302 -0
  117. package/src/style.d.ts +126 -0
  118. package/src/style.js +33 -0
  119. package/src/styles.js +1482 -6
  120. package/src/svgnodes.js +306 -0
  121. package/src/testing/a11y.js +484 -0
  122. package/src/testing/components.js +414 -0
  123. package/src/testing/events.js +407 -0
  124. package/src/testing/harness.js +455 -0
  125. package/src/testing/index.d.ts +558 -0
  126. package/src/testing/index.js +85 -0
  127. package/src/testing/mock-app.js +463 -0
  128. package/src/testing/pixels.js +152 -0
  129. package/src/testing/queries.js +224 -0
  130. package/src/textrange.js +83 -0
  131. package/src/textselection.js +439 -0
  132. package/src/trace-registry.js +63 -0
  133. package/src/transfer.js +93 -0
  134. package/src/types/appearance.d.ts +84 -0
  135. package/src/types/application.d.ts +173 -0
  136. package/src/types/components.d.ts +820 -0
  137. package/src/types/dbus.d.ts +177 -0
  138. package/src/types/elements.d.ts +897 -0
  139. package/src/types/events.d.ts +549 -0
  140. package/src/types/filedialog.d.ts +260 -0
  141. package/src/types/fonts.d.ts +124 -0
  142. package/src/types/frame.d.ts +146 -0
  143. package/src/types/globalmenu.d.ts +42 -0
  144. package/src/types/nodes.d.ts +199 -0
  145. package/src/types/screencolor.d.ts +84 -0
  146. package/src/types/style.d.ts +434 -0
  147. package/src/types/system.d.ts +287 -0
  148. package/src/windowid.js +151 -0
  149. package/src/windowstate.js +393 -0
  150. package/src/xsettings.js +336 -0
  151. package/src/yoga.d.ts +55 -0
  152. package/src/yoga.js +135 -0
  153. package/src/components/Canvas3D.js +0 -28
  154. package/src/geometry3d.js +0 -223
  155. package/src/pointer3d.js +0 -158
  156. package/src/raycast3d.js +0 -146
  157. package/src/richnodes.js +0 -436
  158. package/src/scene3d.js +0 -683
@@ -0,0 +1,223 @@
1
+ // The menu item vocabulary, shared by the component that draws menus
2
+ // (`components/Menu.js`) and the one that hands them to the desktop
3
+ // (`dbusmenu.js`).
4
+ //
5
+ // ## Why the names are the desktop's names
6
+ //
7
+ // A `MenuBar` is either drawn by us or drawn by the panel, and the app is not
8
+ // told which — that is the whole point of the feature. So the descriptor has
9
+ // to be equally at home in both, and only one of the two ends gets a vote on
10
+ // what things are called: `com.canonical.dbusmenu` is a wire protocol with a
11
+ // published item vocabulary, and we are one of many exporters.
12
+ //
13
+ // Hence `type: 'separator'` rather than `separator: true`, `enabled: false`
14
+ // rather than `disabled: true`, `toggleType`/`toggleState` rather than a bare
15
+ // `checked`, and `shortcut` as dbusmenu's `aas` rather than a display string.
16
+ // Each one used to be the shape a drawn-only menu would pick; each one now
17
+ // serialises with no translation, which is what keeps `menus` a single
18
+ // authoring model instead of a drawn one and an exported one that drift.
19
+ //
20
+ // The one deliberate exception is `icon`, which stays a react-x11 callback and
21
+ // is **not** serialisable — see `gutterMark` in `components/Menu.js`. The
22
+ // desktop cannot call a function, so `iconName` and `iconData` are what cross
23
+ // the bus, and an item may carry both: the drawing for our own menu, the theme
24
+ // name for the panel's.
25
+
26
+ /** A rule instead of a row. dbusmenu's `type` property, whose only other legal value is `'standard'`. */
27
+ export const isSeparator = (item) => item?.type === 'separator';
28
+
29
+ /** dbusmenu defaults `enabled` and `visible` to true, so absent means yes. */
30
+ export const isEnabled = (item) => item?.enabled !== false;
31
+ export const isVisible = (item) => item?.visible !== false;
32
+
33
+ /** Can the selection land here? Separators and disabled rows cannot take it. */
34
+ export const isSelectable = (item) =>
35
+ Boolean(item) && !isSeparator(item) && isEnabled(item);
36
+
37
+ /**
38
+ * dbusmenu's `children-display: submenu` — a fact about the children, and
39
+ * about the **visible** ones: a parent whose every child is hidden opens onto
40
+ * nothing, so neither our chevron nor the panel's arrow should promise a
41
+ * submenu that is empty when it arrives.
42
+ */
43
+ export const hasSubmenu = (item) => (item?.items ?? []).some(isVisible);
44
+
45
+ /** Rows the user can see. A hidden item is not laid out, not just not drawn. */
46
+ export const visibleItems = (items) => (items ?? []).filter(isVisible);
47
+
48
+ // --------------------------------------------------------------------------
49
+ // Shortcuts
50
+ // --------------------------------------------------------------------------
51
+
52
+ /**
53
+ * How dbusmenu spells the modifiers. The key token is whatever is left over
54
+ * after them, and it comes last.
55
+ *
56
+ * Exported because a chord is now matched as well as drawn (`accelerators.js`,
57
+ * issue #351), and a second copy of this set in the matcher would be a second
58
+ * answer to "is `Super` a modifier or a key called Super".
59
+ */
60
+ export const MODIFIER_TOKENS = new Set(['Control', 'Alt', 'Shift', 'Super']);
61
+
62
+ /**
63
+ * One `aas` alternative split into what it means: the modifiers held down,
64
+ * in the order they were written, and the key it ends on (`null` for a chord
65
+ * that is nothing but modifiers, which is not a chord).
66
+ *
67
+ * The single reader of the token list — the row draws from it, the panel's
68
+ * announcement spells it, and the key path matches against it.
69
+ */
70
+ export function splitChord(chord) {
71
+ const modifiers = new Set();
72
+ let key = null;
73
+ for (const token of chord ?? []) {
74
+ if (MODIFIER_TOKENS.has(token)) modifiers.add(token);
75
+ else key = token;
76
+ }
77
+ return { modifiers, key };
78
+ }
79
+
80
+ // What a person reads. `Control` is the wire spelling and `Ctrl` is the one
81
+ // every desktop puts in front of a user, which is the entire reason this map
82
+ // is not an identity.
83
+ const MODIFIER_LABELS = {
84
+ Control: 'Ctrl',
85
+ Alt: 'Alt',
86
+ Shift: 'Shift',
87
+ Super: 'Super',
88
+ };
89
+
90
+ // Keys whose name and whose printed form differ. libdbusmenu names a key the
91
+ // way GDK does — `gdk_keyval_name()`, so `plus` rather than `+` — and that is
92
+ // what a panel's importer expects to parse. It is not what a menu should
93
+ // print: `Ctrl+plus` is nobody's idea of a shortcut. Only the ones that
94
+ // actually read badly are here; `F1`, `Delete` and `Home` print themselves.
95
+ const KEY_LABELS = {
96
+ plus: '+',
97
+ minus: '-',
98
+ equal: '=',
99
+ comma: ',',
100
+ period: '.',
101
+ slash: '/',
102
+ backslash: '\\',
103
+ bracketleft: '[',
104
+ bracketright: ']',
105
+ semicolon: ';',
106
+ apostrophe: "'",
107
+ grave: '`',
108
+ space: 'Space',
109
+ Return: 'Enter',
110
+ BackSpace: 'Backspace',
111
+ Prior: 'PgUp',
112
+ Next: 'PgDn',
113
+ };
114
+
115
+ /**
116
+ * One `aas` alternative — `['Control', 'S']` — as the string a menu row
117
+ * shows: `Ctrl+S`.
118
+ *
119
+ * A single-character key is upper-cased because that is how every toolkit
120
+ * prints one, and because dbusmenu carries the *key*, not the character it
121
+ * types: `['Control', 's']` and `['Control', 'S']` are the same binding and
122
+ * must not render differently.
123
+ */
124
+ function formatChord(chord) {
125
+ const { modifiers, key } = splitChord(chord);
126
+ const parts = [...modifiers].map((token) => MODIFIER_LABELS[token]);
127
+ if (key != null) {
128
+ parts.push(KEY_LABELS[key] ?? (key.length === 1 ? key.toUpperCase() : key));
129
+ }
130
+ return parts.join('+');
131
+ }
132
+
133
+ /**
134
+ * `item.shortcut` as the text drawn to the right of a label, or `''`.
135
+ *
136
+ * The prop is dbusmenu's `aas`: a list of **alternatives**, each a list of
137
+ * modifier tokens ending in the key. Only the first alternative is drawn —
138
+ * a row has one shortcut column, and a menu that printed `Ctrl+S / F2` in it
139
+ * would be wider than the menu for the benefit of the rarer binding.
140
+ */
141
+ export function formatShortcut(shortcut) {
142
+ const first = shortcut?.[0];
143
+ if (!Array.isArray(first) || first.length === 0) return '';
144
+ return formatChord(first);
145
+ }
146
+
147
+ // What UI Events calls the modifiers, which is what `aria-keyshortcuts` is
148
+ // specified in terms of. Only `Super` differs from dbusmenu's spelling.
149
+ const ARIA_MODIFIERS = {
150
+ Control: 'Control',
151
+ Alt: 'Alt',
152
+ Shift: 'Shift',
153
+ Super: 'Meta',
154
+ };
155
+
156
+ /**
157
+ * `item.shortcut` as `aria-keyshortcuts`, or `undefined`.
158
+ *
159
+ * A space-delimited list of `+`-joined chords, which is exactly the shape
160
+ * dbusmenu's `aas` already has — so unlike the drawn menu, **every**
161
+ * alternative is announced rather than only the first: a screen reader is
162
+ * reading them out, not fitting them in a column.
163
+ */
164
+ export function ariaKeyShortcuts(shortcut) {
165
+ if (!isValidShortcut(shortcut)) return undefined;
166
+ return shortcut
167
+ .map((chord) =>
168
+ chord
169
+ .map((token) =>
170
+ MODIFIER_TOKENS.has(token)
171
+ ? ARIA_MODIFIERS[token]
172
+ : (KEY_LABELS[token] ?? token),
173
+ )
174
+ .join('+'),
175
+ )
176
+ .join(' ');
177
+ }
178
+
179
+ /**
180
+ * Is this a well-formed `aas`? Used by the development-time check below, and
181
+ * by the exporter, which must not put a malformed shortcut on the wire —
182
+ * dbus-native would throw mid-marshal, inside a method reply, where the
183
+ * failure surfaces as a panel with no menu rather than as an error here.
184
+ */
185
+ export function isValidShortcut(shortcut) {
186
+ return (
187
+ Array.isArray(shortcut) &&
188
+ shortcut.length > 0 &&
189
+ shortcut.every(
190
+ (chord) =>
191
+ Array.isArray(chord) &&
192
+ chord.length > 0 &&
193
+ chord.every((token) => typeof token === 'string' && token.length > 0),
194
+ )
195
+ );
196
+ }
197
+
198
+ let warnedAboutShortcut = false;
199
+
200
+ /**
201
+ * The one shape mistake worth catching for the app author, because both of
202
+ * its failure modes are silent: `shortcut: 'Ctrl+S'` is a string, so
203
+ * `shortcut[0]` is `'C'` and the row draws `C` — and the exporter drops it,
204
+ * so the panel shows no shortcut at all and nothing anywhere says why.
205
+ */
206
+ export function checkShortcut(item) {
207
+ if (process.env.NODE_ENV === 'production') return;
208
+ if (item?.shortcut == null || isValidShortcut(item.shortcut)) return;
209
+ if (warnedAboutShortcut) return;
210
+ warnedAboutShortcut = true;
211
+ console.warn(
212
+ `react-x11: a menu item's \`shortcut\` should be dbusmenu's \`aas\` — a ` +
213
+ 'list of alternatives, each a list of modifier tokens ending in the ' +
214
+ `key — but ${JSON.stringify(item.shortcut)} is not one. Write:\n` +
215
+ " { label: 'Save', shortcut: [['Control', 'S']] }\n" +
216
+ 'Modifier tokens are Control, Alt, Shift and Super.',
217
+ );
218
+ }
219
+
220
+ /** Test seam: the warning above fires once per process. */
221
+ export function _resetShortcutWarning() {
222
+ warnedAboutShortcut = false;
223
+ }