react-x11 2.51.1 → 2.53.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 +94 -61
- package/docs/README.md +256 -0
- package/docs/accessibility.md +575 -0
- package/docs/appearance.md +317 -0
- package/docs/click-to-component.md +92 -0
- package/docs/clipboard.md +262 -0
- package/docs/components.md +1231 -0
- package/docs/dbus.md +205 -0
- package/docs/debugging.md +371 -0
- package/docs/desktop-calendar.md +247 -0
- package/docs/desktop.md +523 -0
- package/docs/devtools.md +133 -0
- package/docs/drag-and-drop.md +585 -0
- package/docs/ecosystem/animation.md +360 -0
- package/docs/ecosystem/data-fetching.md +186 -0
- package/docs/ecosystem/dev-tooling.md +393 -0
- package/docs/ecosystem/forms.md +277 -0
- package/docs/ecosystem/headless.md +194 -0
- package/docs/ecosystem/i18n.md +86 -0
- package/docs/ecosystem/icons.md +377 -0
- package/docs/ecosystem/layout.md +206 -0
- package/docs/ecosystem/routing.md +135 -0
- package/docs/ecosystem/state.md +344 -0
- package/docs/ecosystem/testing.md +474 -0
- package/docs/ecosystem/theming.md +494 -0
- package/docs/ecosystem.md +439 -0
- package/docs/elements.md +2079 -0
- package/docs/embedding.md +239 -0
- package/docs/events.md +742 -0
- package/docs/extending.md +1700 -0
- package/docs/eyedropper.md +164 -0
- package/docs/filedialog.md +222 -0
- package/docs/frame.md +436 -0
- package/docs/gl.md +173 -0
- package/docs/globalmenu.md +195 -0
- package/docs/macos.md +592 -0
- package/docs/notifications.md +150 -0
- package/docs/packaging.md +468 -0
- package/docs/permissions.md +143 -0
- package/docs/react-features.md +405 -0
- package/docs/remote.md +179 -0
- package/docs/scale.md +225 -0
- package/docs/security.md +132 -0
- package/docs/styling.md +1710 -0
- package/docs/system.md +519 -0
- package/docs/testing.md +494 -0
- package/docs/typescript.md +75 -0
- package/docs/uri-schemes.md +340 -0
- package/docs/wayland-backend.md +332 -0
- package/docs/windows-integrations.md +177 -0
- package/docs/windows.md +380 -0
- package/package.json +11 -3
- package/src/Reconciler.js +2 -2
- package/src/a11y.js +1 -1
- package/src/backend/context2d.js +3 -3
- package/src/bootstrap.js +1 -1
- package/src/bus.js +39 -26
- package/src/cli/create.d.ts +43 -0
- package/src/cli/create.js +305 -0
- package/src/cli/env.js +484 -0
- package/src/cli/index.js +29 -2
- package/src/cli/templates/AGENTS.template.md +195 -0
- package/src/cli/templates/DESIGN.template.md +269 -0
- package/src/cocoa/app.js +6 -6
- package/src/cocoa/bezels.js +1 -1
- package/src/cocoa/fonts.js +1 -1
- package/src/cocoa/globalmenu.js +1 -1
- package/src/cocoa/keymap.js +1 -1
- package/src/cocoa/panewindow.js +1 -1
- package/src/cocoa/player.js +1 -1
- package/src/cocoa/presenter.js +2 -2
- package/src/cocoa/promotion.js +1 -1
- package/src/cocoa/relaunch.js +1 -1
- package/src/cocoa/threaded.js +1 -1
- package/src/cocoa/video.js +1 -1
- package/src/cocoa/window.js +4 -4
- package/src/components/Menu.js +7 -2
- package/src/components/Switch.js +1 -1
- package/src/components/native.js +1 -1
- package/src/desktopintegration.js +2 -1
- package/src/desktopsettings.js +193 -24
- package/src/dnd.js +2 -2
- package/src/filedialog.js +3 -3
- package/src/glnodes.js +1 -1
- package/src/grid.js +1 -1
- package/src/keyboardstate.js +28 -0
- package/src/layouts.js +1 -1
- package/src/node.d.ts +10 -10
- package/src/nodes/animation.js +1 -1
- package/src/nodes/invalidate.js +1 -1
- package/src/nodes/layouthost.js +1 -1
- package/src/nodes/video.js +19 -8
- package/src/nodes/window/droptarget.js +1 -1
- package/src/pacing.js +1 -1
- package/src/portal.js +31 -0
- package/src/refresh/index.js +2 -1
- package/src/screencolor.js +5 -10
- package/src/types/system.d.ts +8 -6
- package/src/types/video.d.ts +5 -2
- package/src/videobackend.js +28 -0
- package/src/videoframes.js +29 -16
- package/src/wayland/app.js +86 -0
- package/src/wayland/clipboard.js +14 -7
- package/src/wayland/connection.js +3 -0
- package/src/wayland/context2d.js +129 -10
- package/src/wayland/protocols/index.json +6 -0
- package/src/wayland/protocols/xdg-foreign-unstable-v2.json +1 -0
- package/src/wayland/seat.js +28 -1
- package/src/wayland/swapchain.js +23 -0
- package/src/wayland/video.js +376 -0
- package/src/wayland/xkb.js +137 -0
- package/src/win32/a11y.js +1 -1
- package/src/win32/app.js +2 -2
- package/src/win32/fonts.js +1 -1
- package/src/win32/glarea.js +4 -4
- package/src/win32/overlay.js +1 -1
- package/src/win32/panewindow.js +3 -3
- package/src/win32/shell.js +1 -1
- package/src/win32/window.js +2 -2
- package/src/windowid.js +1 -1
- package/src/xvideo.js +189 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# The global menu
|
|
2
|
+
|
|
3
|
+
Some desktops put an application's menu bar in their own panel rather than in
|
|
4
|
+
its window — Unity's design, still shipped by KDE Plasma's Application Menu
|
|
5
|
+
widget, by `vala-panel-appmenu`, and by several GNOME extensions. On one of
|
|
6
|
+
those, an app that draws its own menu bar is drawing a second one.
|
|
7
|
+
|
|
8
|
+
react-x11 notices and hands the menu over. There is **nothing to configure and
|
|
9
|
+
nothing to call**:
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import { MenuBar } from 'react-x11';
|
|
13
|
+
|
|
14
|
+
<MenuBar
|
|
15
|
+
menus={[
|
|
16
|
+
{
|
|
17
|
+
label: 'File',
|
|
18
|
+
items: [
|
|
19
|
+
{ label: 'New', shortcut: [['Control', 'N']], onSelect: newFile },
|
|
20
|
+
{ type: 'separator' },
|
|
21
|
+
{ label: 'Save As…', enabled: false },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
]}
|
|
25
|
+
/>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Where the platform has somewhere to put a menu, `MenuBar` renders nothing and
|
|
29
|
+
the platform shows this one; where it does not, `MenuBar` draws the bar itself.
|
|
30
|
+
|
|
31
|
+
| where the menu goes | when |
|
|
32
|
+
| ------------------------------------------------------ | ------------------------------------------------------------------------------------- |
|
|
33
|
+
| **the macOS menu bar**, at the top of the screen | the Cocoa backend, always |
|
|
34
|
+
| **the desktop's panel**, over `com.canonical.dbusmenu` | a panel is running one of the applets above |
|
|
35
|
+
| **the window**, drawn by `MenuBar` | everything else — a stock GNOME session, XQuartz, an ssh session, a bare `startx`, CI |
|
|
36
|
+
|
|
37
|
+
On macOS the menu bar takes the menu as soon as `MenuBar` mounts and the drawn
|
|
38
|
+
fallback never renders; see
|
|
39
|
+
[macos.md §Menus](macos.md#menus-the-global-menu-finally-at-home).
|
|
40
|
+
|
|
41
|
+
On Linux the panel row is decided live. The menu leaves the window only once a
|
|
42
|
+
**running** owner of `com.canonical.AppMenu.Registrar` has accepted it (a
|
|
43
|
+
registrar that is merely D-Bus-activatable, as Ubuntu ships it, does not
|
|
44
|
+
count), and it moves into the panel when one starts and back into the window
|
|
45
|
+
when one exits, with no re-render on the app's part. KDE's
|
|
46
|
+
`_KDE_NET_WM_APPMENU_*` window properties are written as well. Design notes:
|
|
47
|
+
[design/globalmenu.md](../design/globalmenu.md).
|
|
48
|
+
|
|
49
|
+
## The item vocabulary is the protocol's
|
|
50
|
+
|
|
51
|
+
`menus` is a plain data prop rather than JSX children, and its item shape is
|
|
52
|
+
`com.canonical.dbusmenu`'s: **the identical array serialises**, so the drawn
|
|
53
|
+
menu and the exported one cannot drift apart.
|
|
54
|
+
|
|
55
|
+
| property | meaning |
|
|
56
|
+
| -------------------------- | ----------------------------------------------------------- |
|
|
57
|
+
| `label` | the row's text |
|
|
58
|
+
| `type` | `'separator'` draws a rule; absent means an ordinary row |
|
|
59
|
+
| `items` | a submenu |
|
|
60
|
+
| `enabled` | defaults to `true`; `false` dims the row and makes it inert |
|
|
61
|
+
| `visible` | defaults to `true`; `false` removes it |
|
|
62
|
+
| `shortcut` | `[['Control', 'S']]` — drawn, exported **and bound** |
|
|
63
|
+
| `toggleType`/`toggleState` | `'checkmark'` or `'radio'`, and `0` / `1` / `-1` |
|
|
64
|
+
| `iconName` | an icon-theme name, for the panel's menu |
|
|
65
|
+
| `iconData` | raw PNG bytes, for an icon that is not in a theme |
|
|
66
|
+
| `disposition` | `'normal'`, `'informative'`, `'warning'`, `'alert'` |
|
|
67
|
+
| `onSelect(item)` | runs whichever menu the click came from |
|
|
68
|
+
| `key` | identity, when the label is not stable |
|
|
69
|
+
|
|
70
|
+
`toggleState` has **three** values, not two: `-1` is _indeterminate_ — a "Bold"
|
|
71
|
+
that is on for part of the selection — and draws as a dash rather than as
|
|
72
|
+
unchecked.
|
|
73
|
+
|
|
74
|
+
`icon` is the one thing that does not cross the bus: it is a react-x11 drawing
|
|
75
|
+
callback ([components.md](components.md#menubar--contextmenu)), so an item that
|
|
76
|
+
wants an icon in both menus carries `icon` for ours and `iconName` for the
|
|
77
|
+
panel's.
|
|
78
|
+
|
|
79
|
+
Building `menus` inline on every render is fine: only what changed is sent to
|
|
80
|
+
the panel, and item identity (the path of `key ?? label`) survives re-renders.
|
|
81
|
+
|
|
82
|
+
### Shortcuts are a list, not a string
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
shortcut: [['Control', 'S']];
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The outer array is a list of _alternatives_; each inner one is modifier tokens
|
|
89
|
+
(`Control`, `Alt`, `Shift`, `Super`) ending in the key. Only the first is
|
|
90
|
+
drawn — a row has one shortcut column.
|
|
91
|
+
|
|
92
|
+
**On macOS, `Control` means ⌘** — the primary modifier — so `[['Control', 'S']]`
|
|
93
|
+
becomes ⌘S in the menu bar. `Super` maps there too; `Shift` and `Alt` are
|
|
94
|
+
themselves. A chord the `NSMenu` spelling cannot express is not printed beside
|
|
95
|
+
the item, but the binding still fires (the app's window answers it, below).
|
|
96
|
+
The text controls' chords, the edit menu that prints them
|
|
97
|
+
([events.md](events.md#primary-modifier)) and the window's own bindings
|
|
98
|
+
(`useAccelerator`, a drawn `MenuBar` or `ContextMenu`, which prints `⌘S` beside
|
|
99
|
+
the row — [events.md](events.md#the-chord)) follow the same rule.
|
|
100
|
+
|
|
101
|
+
The key is named the way GDK names it, so `plus` rather than `+` and `Prior`
|
|
102
|
+
rather than `PgUp`, because that is what a panel's importer parses. Menus print
|
|
103
|
+
the friendly form: `[['Control', 'plus']]` draws as `Ctrl++`.
|
|
104
|
+
|
|
105
|
+
**It is a binding**, and the app writes it once. A mounted `MenuBar` answers
|
|
106
|
+
its own items' chords: Ctrl+S fires the item's `onSelect` without the menu
|
|
107
|
+
being opened, gated by that item's own `enabled` and `visible`
|
|
108
|
+
([events.md](events.md#accelerators)).
|
|
109
|
+
|
|
110
|
+
When the panel draws the menu, the **panel does not deliver the key**, so
|
|
111
|
+
`MenuBar` keeps its bindings when it stops drawing. `accelerators={false}`
|
|
112
|
+
turns them off for an application with a dispatcher of its own.
|
|
113
|
+
|
|
114
|
+
The macOS menu bar is the one delegate that **does** deliver keys: it runs an
|
|
115
|
+
item on the ⌘ chord installed as its key equivalent, after the window has seen
|
|
116
|
+
the key. So there `MenuBar` reserves those chords — no binding in the window
|
|
117
|
+
answers them, its own included, and the item runs once — and keeps answering
|
|
118
|
+
the chords no `NSMenu` key equivalent can spell
|
|
119
|
+
([events.md](events.md#the-macos-menu-bar)).
|
|
120
|
+
|
|
121
|
+
## Seeing it work, without a desktop that has one
|
|
122
|
+
|
|
123
|
+
In a checkout of this repo, a stand-in panel prints every menu handed to it:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm run globalmenu:host
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
In another terminal:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm run examples:menu
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The window's own menu bar disappears and the menu appears in the host. Type an
|
|
136
|
+
item's id and press Enter to activate it; Ctrl-C the host and the bar returns
|
|
137
|
+
to the window. On a machine with a real panel,
|
|
138
|
+
`npm run globalmenu:host -- --watch` attaches to the live registrar instead.
|
|
139
|
+
|
|
140
|
+
## Turning it off
|
|
141
|
+
|
|
142
|
+
```jsx
|
|
143
|
+
<MenuBar menus={menus} globalMenu={false} />
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
REACT_X11_NO_GLOBAL_MENU=1
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```jsx
|
|
151
|
+
await createRoot({ desktop: { globalMenu: false } });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The prop is for one bar. The other two are process-wide: the environment
|
|
155
|
+
variable needs no application change (for a user working around a panel that
|
|
156
|
+
renders something badly), and the `createRoot` option is the one an embedder
|
|
157
|
+
can set without it leaking to child processes — see
|
|
158
|
+
[desktop.md](desktop.md#turning-the-desktop-off), where `desktop: false` turns
|
|
159
|
+
this off along with the other session-bus integrations.
|
|
160
|
+
|
|
161
|
+
## Drawing your own bar
|
|
162
|
+
|
|
163
|
+
`MenuBar` does all of this itself. A component that draws its own can have the
|
|
164
|
+
same behaviour:
|
|
165
|
+
|
|
166
|
+
```jsx
|
|
167
|
+
import { useGlobalMenu } from 'react-x11';
|
|
168
|
+
|
|
169
|
+
function Bar({ menus }) {
|
|
170
|
+
const exported = useGlobalMenu(menus, { onSelect });
|
|
171
|
+
if (exported) return null; // the panel has it
|
|
172
|
+
return; /* … your bar … */
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Known limits, so they are not rediscovered as bugs
|
|
177
|
+
|
|
178
|
+
- **Stock GNOME has no global menu bar at all**, so the in-window bar stays.
|
|
179
|
+
The extensions that add one work.
|
|
180
|
+
- **`ContextMenu` is not exported** — a right-click menu belongs where the
|
|
181
|
+
pointer is.
|
|
182
|
+
- **One menu per window.** A second `MenuBar` in a window that already has one
|
|
183
|
+
stays drawn in the window until the first unmounts or turns `globalMenu`
|
|
184
|
+
off, and only then takes the panel. A bar remounted with a new `key`, or
|
|
185
|
+
switched off and on again, waits the same way for the one it replaces to
|
|
186
|
+
finish leaving (a round trip or two).
|
|
187
|
+
- **A lazily-built submenu fills in one round trip late.** `onAboutToShow`
|
|
188
|
+
runs when the panel opens the submenu, and the new items reach the panel
|
|
189
|
+
once they have rendered.
|
|
190
|
+
- **`org.gtk.Menus`/`org.gtk.Actions` is not exported**; Plasma and the GNOME
|
|
191
|
+
extensions consume dbusmenu.
|
|
192
|
+
- **No bus is a first-class configuration.** Everything here degrades to
|
|
193
|
+
"draw the bar" without logging: no `dbus-native` (Node 20), no
|
|
194
|
+
`$DBUS_SESSION_BUS_ADDRESS`, a connection that fails. See
|
|
195
|
+
[dbus.md](dbus.md).
|