buninu-browser 0.3.0 → 0.4.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/LICENSES/jsmdcui.txt +22 -0
- package/README.md +19 -4
- package/frontends/wayland/LICENSE-land +21 -0
- package/frontends/wayland/README.md +123 -0
- package/frontends/wayland/casty/LICENSE +21 -0
- package/frontends/wayland/casty/bookmarks.js +32 -0
- package/frontends/wayland/casty/click.js +96 -0
- package/frontends/wayland/casty/commands.js +61 -0
- package/frontends/wayland/casty/config.js +45 -0
- package/frontends/wayland/casty/download-directory.js +28 -0
- package/frontends/wayland/casty/download.js +49 -0
- package/frontends/wayland/casty/hints.js +334 -0
- package/frontends/wayland/casty/keys.js +56 -0
- package/frontends/wayland/casty/page-commands.js +80 -0
- package/frontends/wayland/casty/prompt-width.js +148 -0
- package/frontends/wayland/casty/urlbar.js +606 -0
- package/frontends/wayland/client.js +88 -0
- package/frontends/wayland/clipboard.js +80 -0
- package/frontends/wayland/index.js +116 -0
- package/frontends/wayland/input.js +56 -0
- package/frontends/wayland/protocol.js +55 -0
- package/frontends/wayland/protocols/wayland.xml +3248 -0
- package/frontends/wayland/protocols/xdg-shell.xml +1415 -0
- package/frontends/wayland/transport.js +120 -0
- package/frontends/wayland/urlbar.js +158 -0
- package/index.js +28 -1
- package/lib/clipboard-command.js +10 -0
- package/lib/clipboard-powershell.js +22 -0
- package/lib/clipboard.js +37 -2
- package/lib/document-types.js +11 -0
- package/lib/headless-shell.js +47 -8
- package/lib/layout/text-layout.js +17 -9
- package/lib/paint/display-list.js +5 -1
- package/lib/qml/README.md +971 -0
- package/lib/qml/builtins.js +700 -0
- package/lib/qml/canvas-dom.js +115 -0
- package/lib/qml/document.js +1176 -0
- package/lib/qml/format.js +9 -0
- package/lib/qml/host.js +324 -0
- package/lib/qml/images.js +199 -0
- package/lib/qml/launcher.js +132 -0
- package/lib/qml/loader.js +517 -0
- package/lib/qml/media-renderer.js +49 -0
- package/lib/qml/media.js +86 -0
- package/lib/qml/models.js +622 -0
- package/lib/qml/parser.js +381 -0
- package/lib/qml/qs +5 -0
- package/lib/qml/qscasty +3 -0
- package/lib/qml/qsheadless +3 -0
- package/lib/qml/qswayland +3 -0
- package/lib/qml/reactive.js +159 -0
- package/lib/qml/runtime.js +3381 -0
- package/lib/qml/shapes.js +243 -0
- package/lib/qml/text.js +109 -0
- package/lib/qml/textures.js +123 -0
- package/lib/qml/wayland-clipboard.js +32 -0
- package/lib/qml/worker-thread.js +70 -0
- package/lib/render-tree/index.js +16 -1
- package/lib/renderer/bindings.js +11 -0
- package/lib/renderer/canvas-2d.js +13 -0
- package/lib/renderer/host.js +31 -6
- package/lib/renderer/main.js +19 -6
- package/lib/renderer/page-realm.js +16 -1
- package/lib/renderer/page-renderer.js +230 -13
- package/lib/renderer/text-input-paint.js +54 -0
- package/lib/renderer/text-input.js +57 -0
- package/lib/style/computed-style.js +2 -2
- package/package.json +1 -1
- package/test/clipboard.test.js +19 -0
- package/test/fixtures/flea-helpers/Dockerfile +36 -0
- package/test/fixtures/flea-helpers/bat.mjs +43 -0
- package/test/fixtures/flea-helpers/bin/bat +3 -0
- package/test/fixtures/flea-helpers/bin/bwrap +10 -0
- package/test/fixtures/flea-helpers/bin/bwrap-real-filter +9 -0
- package/test/fixtures/flea-helpers/bin/glow +3 -0
- package/test/fixtures/flea-helpers/bin/qs +3 -0
- package/test/fixtures/flea-helpers/bin/unsupported +3 -0
- package/test/fixtures/flea-helpers/check-highlighting.mjs +47 -0
- package/test/fixtures/flea-helpers/check-media.mjs +29 -0
- package/test/fixtures/flea-helpers/check-preview.mjs +27 -0
- package/test/fixtures/flea-helpers/check.mjs +36 -0
- package/test/fixtures/flea-helpers/highlight-cases.json +227 -0
- package/test/fixtures/flea-helpers/source-mime.xml +28 -0
- package/test/fixtures/flea-helpers/syntax-compat.mjs +23 -0
- package/test/fixtures/flea-thumbnail-stub/flea-placeholder.thumbnailer +4 -0
- package/test/fixtures/flea-thumbnail-stub/flea-thumbnail-stub +3 -0
- package/test/fixtures/qml/flea/EscapeHint.qml +11 -0
- package/test/fixtures/qml/flea/LICENSE +21 -0
- package/test/fixtures/qml/flea/README.md +25 -0
- package/test/fixtures/qml/flea/Theme.qml +8 -0
- package/test/fixtures/qml/flea/demo.qml +24 -0
- package/test/fixtures/qml/flea/qmldir +3 -0
- package/test/fixtures/qml/flea-theme/LICENSE-Flea +21 -0
- package/test/fixtures/qml/flea-theme/LICENSE-Omarchy +20 -0
- package/test/fixtures/qml/flea-theme/README.md +70 -0
- package/test/fixtures/qml/flea-theme/button.qml +17 -0
- package/test/fixtures/qml/flea-theme/demo.qml +27 -0
- package/test/fixtures/qml/flea-theme/field.qml +21 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/BorderGeometry.js +373 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Color.qml +258 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/I18n.qml +118 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Numbers.js +19 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Plural.js +91 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Style.qml +561 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/Util.qml +188 -0
- package/test/fixtures/qml/flea-theme/imports/qs/Commons/qmldir +13 -0
- package/test/fixtures/qml/flea-theme/segment.qml +17 -0
- package/test/fixtures/qml/flea-theme/settings.qml +58 -0
- package/test/fixtures/qml/flea-theme/text-metrics.qml +10 -0
- package/test/fixtures/qml/flea-theme/ui/DialogButton.qml +150 -0
- package/test/fixtures/qml/flea-theme/ui/DialogField.qml +147 -0
- package/test/fixtures/qml/flea-theme/ui/EscapeHint.qml +11 -0
- package/test/fixtures/qml/flea-theme/ui/Glass.qml +114 -0
- package/test/fixtures/qml/flea-theme/ui/Glyph.qml +54 -0
- package/test/fixtures/qml/flea-theme/ui/GlyphSolid.qml +22 -0
- package/test/fixtures/qml/flea-theme/ui/Reveal.qml +54 -0
- package/test/fixtures/qml/flea-theme/ui/SettingsRuler.qml +85 -0
- package/test/fixtures/qml/flea-theme/ui/SettingsSegment.qml +85 -0
- package/test/fixtures/qml/flea-theme/ui/StableModel.qml +89 -0
- package/test/fixtures/qml/flea-theme/ui/Theme.qml +460 -0
- package/test/fixtures/qml/flea-theme/ui/ThemeColors.qml +43 -0
- package/test/fixtures/qml/flea-theme/ui/ViewState.qml +565 -0
- package/test/fixtures/qml/flea-theme/ui/js/Anchor.js +379 -0
- package/test/fixtures/qml/flea-theme/ui/js/AnchorHold.js +162 -0
- package/test/fixtures/qml/flea-theme/ui/js/Archive.js +157 -0
- package/test/fixtures/qml/flea-theme/ui/js/BackReturn.js +110 -0
- package/test/fixtures/qml/flea-theme/ui/js/Buttons.js +54 -0
- package/test/fixtures/qml/flea-theme/ui/js/ColumnMenu.js +111 -0
- package/test/fixtures/qml/flea-theme/ui/js/Columns.js +298 -0
- package/test/fixtures/qml/flea-theme/ui/js/Contrast.js +157 -0
- package/test/fixtures/qml/flea-theme/ui/js/Density.js +44 -0
- package/test/fixtures/qml/flea-theme/ui/js/DirSizes.js +129 -0
- package/test/fixtures/qml/flea-theme/ui/js/ExtThumbs.js +115 -0
- package/test/fixtures/qml/flea-theme/ui/js/Filter.js +284 -0
- package/test/fixtures/qml/flea-theme/ui/js/FolderSorts.js +108 -0
- package/test/fixtures/qml/flea-theme/ui/js/Format.js +305 -0
- package/test/fixtures/qml/flea-theme/ui/js/Icons.js +206 -0
- package/test/fixtures/qml/flea-theme/ui/js/Input.js +39 -0
- package/test/fixtures/qml/flea-theme/ui/js/KeyName.js +64 -0
- package/test/fixtures/qml/flea-theme/ui/js/Keymap.js +370 -0
- package/test/fixtures/qml/flea-theme/ui/js/Kinds.js +145 -0
- package/test/fixtures/qml/flea-theme/ui/js/Lists.js +11 -0
- package/test/fixtures/qml/flea-theme/ui/js/MakeDefault.js +186 -0
- package/test/fixtures/qml/flea-theme/ui/js/Match.js +27 -0
- package/test/fixtures/qml/flea-theme/ui/js/Material.js +109 -0
- package/test/fixtures/qml/flea-theme/ui/js/Menu.js +513 -0
- package/test/fixtures/qml/flea-theme/ui/js/Motion.js +16 -0
- package/test/fixtures/qml/flea-theme/ui/js/Mounts.js +320 -0
- package/test/fixtures/qml/flea-theme/ui/js/MouseNav.js +13 -0
- package/test/fixtures/qml/flea-theme/ui/js/Nav.js +328 -0
- package/test/fixtures/qml/flea-theme/ui/js/Palette.js +33 -0
- package/test/fixtures/qml/flea-theme/ui/js/Places.js +236 -0
- package/test/fixtures/qml/flea-theme/ui/js/Protocols.js +296 -0
- package/test/fixtures/qml/flea-theme/ui/js/RecentMode.js +154 -0
- package/test/fixtures/qml/flea-theme/ui/js/Search.js +396 -0
- package/test/fixtures/qml/flea-theme/ui/js/Settings.js +476 -0
- package/test/fixtures/qml/flea-theme/ui/js/SettingsAbout.js +99 -0
- package/test/fixtures/qml/flea-theme/ui/js/SettingsShelf.js +52 -0
- package/test/fixtures/qml/flea-theme/ui/js/Sort.js +127 -0
- package/test/fixtures/qml/flea-theme/ui/js/StateWords.js +42 -0
- package/test/fixtures/qml/flea-theme/ui/js/Swap.js +166 -0
- package/test/fixtures/qml/flea-theme/ui/js/TextSize.js +107 -0
- package/test/fixtures/qml/flea-theme/ui/js/Thumbs.js +158 -0
- package/test/fixtures/qml/flea-theme/ui/js/UiState.js +438 -0
- package/test/fixtures/qml/flea-theme/ui/js/Update.js +132 -0
- package/test/fixtures/qml/flea-theme/ui/js/UserDirs.js +56 -0
- package/test/fixtures/qml/flea-theme/ui/qmldir +227 -0
- package/test/fixtures/qml/hello.qml +26 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabel.qml +2 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabelNew.qml +2 -0
- package/test/fixtures/qml/imports/Demo/Toolkit/qmldir +3 -0
- package/test/fixtures/qml/imports/components/Badge.qml +15 -0
- package/test/fixtures/qml/imports/logic/base.js +2 -0
- package/test/fixtures/qml/imports/logic/counter.js +4 -0
- package/test/fixtures/qml/imports/logic/math.js +3 -0
- package/test/fixtures/qml/imports/logic/shared.js +3 -0
- package/test/fixtures/qml/imports/main.qml +21 -0
- package/test/fixtures/qml/imports/theme/Theme.qml +8 -0
- package/test/fixtures/qml/imports/theme/qmldir +2 -0
- package/test/fixtures/qml/multiply.qml +61 -0
- package/test/fixtures/qml-canvas-dom.js +90 -0
- package/test/fixtures/qml-media-audio.js +39 -0
- package/test/helpers/flea-sandbox.js +48 -0
- package/test/helpers/quickshell-fixture.js +125 -0
- package/test/html-clipboard-wayland.test.js +47 -0
- package/test/index.test.js +13 -0
- package/test/manual-casty-without-qml.js +87 -0
- package/test/manual-flea-application.js +49 -0
- package/test/manual-flea-binary.js +62 -0
- package/test/manual-flea-qml.js +9 -0
- package/test/manual-flea-settings.js +40 -0
- package/test/manual-flea-theme.js +40 -0
- package/test/manual-qml-removal.js +46 -0
- package/test/manual-without-qml.js +45 -0
- package/test/qml-canvas-dom.test.js +37 -0
- package/test/qml-clipboard-bridge.test.js +25 -0
- package/test/qml-clipboard-wayland.test.js +40 -0
- package/test/qml-connections-timing.test.js +73 -0
- package/test/qml-dynamic.test.js +401 -0
- package/test/qml-flea-app.test.js +146 -0
- package/test/qml-flea-backend.test.js +78 -0
- package/test/qml-flea-columns-backend.test.js +38 -0
- package/test/qml-flea-compile.test.js +78 -0
- package/test/qml-flea-launcher.test.js +88 -0
- package/test/qml-flea-markdown-backend.test.js +31 -0
- package/test/qml-flea-media.test.js +28 -0
- package/test/qml-flea-navigation-backend.test.js +35 -0
- package/test/qml-flea-navigation-timing.test.js +147 -0
- package/test/qml-flea-preview-backend.test.js +53 -0
- package/test/qml-flea-previews.test.js +163 -0
- package/test/qml-flea-rows.test.js +101 -0
- package/test/qml-flea-textures.test.js +59 -0
- package/test/qml-flea-view-switch.test.js +33 -0
- package/test/qml-flea-wayland.test.js +68 -0
- package/test/qml-flea.test.js +34 -0
- package/test/qml-host.test.js +238 -0
- package/test/qml-imports.test.js +102 -0
- package/test/qml-inherited-handlers.test.js +51 -0
- package/test/qml-input-selection.test.js +66 -0
- package/test/qml-interactions.test.js +309 -0
- package/test/qml-language.test.js +167 -0
- package/test/qml-launcher.test.js +54 -0
- package/test/qml-layout-text.test.js +205 -0
- package/test/qml-media.test.js +63 -0
- package/test/qml-persisted-delegates.test.js +45 -0
- package/test/qml-quickshell-controls.test.js +65 -0
- package/test/qml-quickshell-settings.test.js +62 -0
- package/test/qml-repeater.test.js +72 -0
- package/test/qml-style-updates.test.js +124 -0
- package/test/qml-textures.test.js +66 -0
- package/test/qml-views.test.js +332 -0
- package/test/qml-worker.test.js +69 -0
- package/test/qml.test.js +83 -0
- package/test/renderer-host.test.js +11 -0
- package/test/text-input-pointer.test.js +31 -0
- package/test/text-input-scroll.test.js +29 -0
- package/test/text-input.test.js +47 -0
- package/test/wayland-frontend.test.js +83 -0
- package/test/wayland-urlbar.test.js +38 -0
|
@@ -0,0 +1,971 @@
|
|
|
1
|
+
# Experimental QML DOM frontend
|
|
2
|
+
|
|
3
|
+
QML is compiled directly into this browser's existing DOM, CSS and page JavaScript.
|
|
4
|
+
It does not generate HTML or retain a second QML component tree. Temporary syntax
|
|
5
|
+
and import graphs are discarded after generating DOM factories and bindings.
|
|
6
|
+
Flat property state, DOM references, delegate factories and reactive dependencies
|
|
7
|
+
remain. No new npm dependency or native Qt library is required.
|
|
8
|
+
|
|
9
|
+
This is an experimental subset, not a QtQuick/Quickshell replacement. Unknown
|
|
10
|
+
imports, types and properties produce diagnostics. Recognized APIs also have
|
|
11
|
+
limits documented below; successful compilation is not complete compatibility.
|
|
12
|
+
|
|
13
|
+
## Try it
|
|
14
|
+
|
|
15
|
+
Run these commands from the buninu-browser repository:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
bun index.js file://"$PWD"/test/fixtures/qml/multiply.qml
|
|
19
|
+
bun index.js --wayland file://"$PWD"/test/fixtures/qml/multiply.qml
|
|
20
|
+
bun test test/qml*.test.js
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The same three-field calculator has been checked with the real Quickshell binary.
|
|
24
|
+
QML is recognized by `text/x-qml`, `application/x-qml`, or a `.qml` path with a
|
|
25
|
+
text/generic MIME type. Explicit HTML retains HTML behavior. With scripting off,
|
|
26
|
+
the source is displayed inertly. Downloads retain the original bytes.
|
|
27
|
+
|
|
28
|
+
The standard Wayland frontend uses `WAYLAND_DISPLAY` and `XDG_RUNTIME_DIR` and
|
|
29
|
+
presents ordinary `wl_shm` buffers. One browser frontend currently owns one native
|
|
30
|
+
window; multiple QML `FloatingWindow` objects do not create multiple OS windows.
|
|
31
|
+
The root fills the supplied viewport and follows its resize events.
|
|
32
|
+
|
|
33
|
+
## Opt-in `qs` wrapper and official Flea binary
|
|
34
|
+
|
|
35
|
+
`lib/qml/qs` is an executable Bun launcher, accepting `-p/--path` (file or
|
|
36
|
+
configuration directory) and `-c/--config`. Put its directory first in PATH
|
|
37
|
+
**for this application only**; it does not replace an installed Quickshell.
|
|
38
|
+
Unknown arguments, including native `qs ipc`, fail explicitly. This is still
|
|
39
|
+
our experimental DOM runtime, not the native Quickshell engine.
|
|
40
|
+
|
|
41
|
+
For an already extracted Omarchy package and the existing Omarchy QML reference:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
FLEA_BIN=/path/to/package-root/usr/bin/flea \
|
|
45
|
+
BUNINU_FLEA_ROOT=/path/to/package-root/usr/share/flea \
|
|
46
|
+
BUNINU_OMARCHY_ROOT=/opt/omarchy-source \
|
|
47
|
+
bun test/manual-flea-binary.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This creates a temporary HOME/XDG state and sample files, then runs the **actual
|
|
51
|
+
Flea binary** with `--gui`. A temporary PATH directory contains a `qs` symlink
|
|
52
|
+
to `lib/qml/qswayland`. Flea calls `qs -p .../boot/shell.qml` and
|
|
53
|
+
supplies `FLEA_BIN`/`FLEA_PATH`; the wrapper preserves that environment and opens
|
|
54
|
+
the ordinary Wayland frontend. Closing the window removes the temporary state.
|
|
55
|
+
The script sets the upstream Qt renderer hint to `opengl` only to avoid Flea's
|
|
56
|
+
native Vulkan probe; our renderer remains the browser's existing renderer.
|
|
57
|
+
|
|
58
|
+
To use your own settings, the equivalent direct invocation is:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
env PATH="$PWD/lib/qml:$PATH" \
|
|
62
|
+
FLEA_UI=/path/to/package-root/usr/share/flea/ui \
|
|
63
|
+
QML_IMPORT_PATH=/path/to/imports \
|
|
64
|
+
QSG_RHI_BACKEND=opengl \
|
|
65
|
+
/path/to/package-root/usr/bin/flea --gui /path/to/directory
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The import root must contain `qs/Commons` and `qs/Ui` pointing to the Omarchy
|
|
69
|
+
QML modules; the manual runner creates these links itself. Keep the backend and
|
|
70
|
+
Flea QML from the same package. `WAYLAND_DISPLAY`/`XDG_RUNTIME_DIR` select Land.
|
|
71
|
+
A real launch uses your settings and file access, like other local QML programs.
|
|
72
|
+
|
|
73
|
+
Omarchy stable **0.3.12-1 aarch64** was tested on Debian proot: the original
|
|
74
|
+
binary launches our wrapper, a real `--backend` child lists files, directory
|
|
75
|
+
watch notifications update rows, Ctrl-L/Enter navigates to a directory, and
|
|
76
|
+
Land's Super-W closes the wrapper. The settings controls also pass against
|
|
77
|
+
this binary. `DelegateModel.items.create()` now supplies persisted membership
|
|
78
|
+
before completion; views adopt those parked items without constructing duplicates.
|
|
79
|
+
|
|
80
|
+
Wrapper validation: 60 general QML tests passed (17 opt-in cases skipped),
|
|
81
|
+
the two real-backend/official-launcher tests passed with the above environment,
|
|
82
|
+
and the official-backend settings test passed separately. The removable-integration
|
|
83
|
+
check still passed all 9 ordinary-browser tests. No integration outside `lib/qml`
|
|
84
|
+
or `test` was added for this wrapper.
|
|
85
|
+
|
|
86
|
+
List view and the ShaderEffectSource-dependent preview components now compile.
|
|
87
|
+
Headless tests exercise real text/PNG Quick Look navigation with the official
|
|
88
|
+
backend, plus unchanged PreviewSwap/HtmlClip pixel behavior. This does not claim
|
|
89
|
+
complete Columns-view coverage, file operation safety coverage, or native QS IPC.
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
# Same environment as above, with BUNINU_QML_WAYLAND_TEST=1 for the socket test:
|
|
93
|
+
bun test test/qml-flea-backend.test.js test/qml-flea-launcher.test.js
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Flea依賴的外部環境和工具
|
|
97
|
+
|
|
98
|
+
- **Android 第一步:在原生 Termux 開 jsgotty**:先確認 Termux 原生的 Bun 可用,不要在 Debian proot 裡執行這一步。保持這個 Termux 工作階段開著。
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
bun --version
|
|
102
|
+
bunx jsgotty -w -r --session bash
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`-w` 允許鍵盤輸入,`-r` 產生隨機網址路徑,`--session` 保留可重新連接的 shell。用手機瀏覽器/WebView 打開 jsgotty 印出的完整網址;同一手機可用 `127.0.0.1:8080`,但要保留印出的隨機路徑,不能只開首頁。這裡的 `-r` 是 server 的 random URL,不是 `--client -r PID`。
|
|
106
|
+
|
|
107
|
+
- **Android 第二步:在瀏覽器裡的終端開 Land**:進入上述 jsgotty 畫面後執行以下命令,保持它運行。使用的是宿主 Termux 的 Bun;首次執行可能下載 Land/Casty。
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
env XDG_RUNTIME_DIR="$TMPDIR" bunx buninu-land
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Land 的顯示留在這個瀏覽器視窗。預設 socket 是 `$TMPDIR/wayland-buninu`;若已有其他 Land,名稱可能是 `wayland-buninu1` 等,請以 Land 顯示的地址為準。
|
|
114
|
+
|
|
115
|
+
- **需要聲音時:在宿主另外啟動 jspulse**:Android/Termux 使用 OpenSL ES;在另一個原生 Termux shell 執行並保持運行,不是在容器裡啟動。若已有 jspulse 服務就沿用,不必重複開。
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
bunx @drxiaozhi/jspulse --sles
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
一般 Linux 有 ALSA 裝置時,改用以下命令;這是兩種環境的替代選項,不是一起執行。
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
bunx @drxiaozhi/jspulse --alsa
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
播放前先確認音量,必要時先 **unmute**;ALSA 音效卡的播放開關、音量,以及 Flea 自己的靜音按鈕都可能影響出聲。Android 也要確認系統媒體音量。選卡、音量與解除靜音的操作詳見 jspulse 手冊:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
bunx @drxiaozhi/jspulse --readme
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
播放器沿用 `127.0.0.1:4713`。Termux 的 js-udocker/proot 共用宿主網路,可直接連到該服務;一般 Docker 若另有網路隔離,需另安排 host 音訊服務的連線,不能假設容器的 localhost 就是宿主。沒有音訊服務仍可操作 Flea,但不能據此宣稱已驗證出聲。
|
|
134
|
+
|
|
135
|
+
- **Android 第三步:另開一個原生 Termux shell,安裝 js-udocker**:不是在 Land 網址列輸入,也不是進入 Debian 後才裝。安裝腳本名稱是專案內附的 `termux_install.sh`;它會把 `udocker` 指向該 checkout,因此之後不要搬走或刪掉 checkout。wrapper 使用 Node.js 和 proot;已有這些套件可以略過 pkg 指令。
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
pkg install git nodejs proot curl tar
|
|
139
|
+
cd "$HOME"
|
|
140
|
+
git clone https://github.com/jjtseng93/js-udocker.git
|
|
141
|
+
cd js-udocker
|
|
142
|
+
sh termux_install.sh
|
|
143
|
+
hash -r
|
|
144
|
+
command -v udocker
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- **Android 第四步:取得本專案作為 build context**:繼續在第二個 Termux shell 執行。已有 buninu-browser checkout 時直接進入該目錄,並確保它包含這份 Dockerfile;不要在主專案執行 bun i,jsmdcui 會由 Dockerfile 安裝到容器的獨立 helper 目錄。
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
cd "$HOME"
|
|
151
|
+
git clone https://github.com/jjtseng93/buninu-browser.git
|
|
152
|
+
cd buninu-browser
|
|
153
|
+
test -f test/fixtures/flea-helpers/Dockerfile
|
|
154
|
+
test -S "$TMPDIR/wayland-buninu"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
接著才執行下方的 `udocker build`/`udocker run`。容器透過 `-b "$TMPDIR:/tmp"` 使用剛剛的 Land;若實際 socket 是 `wayland-buninu1`,run 時再加 `-e WAYLAND_DISPLAY=wayland-buninu1`。回到瀏覽器即可看到 Flea,不必在容器裡再啟動 Land。
|
|
158
|
+
|
|
159
|
+
- **直接建置:Dockerfile**:[test/fixtures/flea-helpers/Dockerfile](../../test/fixtures/flea-helpers/Dockerfile) 從固定的 `oven/bun:1.4.4` 開始,取得 Omarchy 官方 Flea 0.3.12-1、固定 revision 的 Omarchy QML,安裝 MIME 資料、基本 shell 工具及獨立的 `jsmdcui@0.19.2`,並複製本專案瀏覽器與所有 wrapper。**在原生 Termux 執行**,不要在既有 Debian proot 內再建置。先將完整 buninu-browser 專案設為目前目錄;`udocker` 是已安裝的 js-udocker 命令。建置會下載套件、建立新容器,不會把 node_modules 放到主專案。
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
udocker build -t flea-qml -y -f test/fixtures/flea-helpers/Dockerfile .
|
|
163
|
+
udocker run -b "$TMPDIR:/tmp" flea-qml
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Land 須已在原生端啟動,socket 為 `$TMPDIR/wayland-buninu`。映像預設開 `/root/flea-demo`,包含文字、MP3、MP4。改目錄可用 `udocker run -b "$TMPDIR:/tmp" flea-qml /usr/bin/flea --gui /root`。Dockerfile 僅使用單階段 FROM、簡單 COPY、shell RUN、每行一組 `ENV KEY=value`、WORKDIR、JSON ENTRYPOINT/CMD;不用 BuildKit、heredoc、COPY --chmod 或一行多組 ENV。這份映像明確啟用無隔離的 bwrap 實驗替代與佔位縮圖,不包含原生 Qt/Quickshell。官方套件若從鏡像移除,建置會下載失敗,不會自動改用未知版本。
|
|
167
|
+
|
|
168
|
+
建置中的 [check.mjs](../../test/fixtures/flea-helpers/check.mjs) 檢查 Bun 版本、MIME、Omarchy 模組、jsmdcui 真實 ANSI 上色、官方 Flea 後端的 45 種格式/90 組上色請求、縮圖回覆與 QML DOM 截圖。也可手動重跑 `udocker run flea-qml bun /usr/local/lib/flea-helpers/check.mjs`;Termux 若在 base image 解壓時顯示 Perl 硬連結被拒,Dockerfile 會在第一個 RUN 補成普通檔案;其他解壓錯誤不能一概忽略。不能只以 js-udocker 最外層退出碼判定成功,應確認 `PASS:` 訊息,因目前 builder 可能繼續執行失敗 RUN 後的指令。2026-10-24 已從原生 Termux 實測 `build -t flea-qml`,上述檢查全過,並用 `udocker run -b "$TMPDIR:/tmp" flea-qml` 連到 Land,截圖確認三個範例檔案出現在視窗中。
|
|
169
|
+
|
|
170
|
+
**接下來是詳細說明**:若已依上面的 Dockerfile 建置並成功啟動 Flea,就可以直接使用,不必再執行以下安裝步驟。以下逐項解釋依賴、wrapper 與替代方案,供手動建立環境、調整功能或排查問題時參考。
|
|
171
|
+
|
|
172
|
+
- **範圍與順序**:以下以已驗證的 Flea **0.3.12-1**、Debian 13、Bun、已啟動的 Land 為基準;若選擇手動配置,依序做完「必要」與「實驗替代」項目,就能啟動檔案列表、文字上色及影音預覽。不是完整 Omarchy,也不保證垃圾桶、掛載、PDF、桌面服務都可用。所有本文使用的 wrapper 都收錄在本專案 [test/fixtures/flea-helpers](../../test/fixtures/flea-helpers/) 或 [test/fixtures/flea-thumbnail-stub](../../test/fixtures/flea-thumbnail-stub/),不需要隔壁專案或作者的既有容器。每個 shell wrapper/stub 都不超過 10 行;`bat.mjs` 是保留實際上色功能的完整適配器,不是假成功 stub。
|
|
173
|
+
|
|
174
|
+
- **必要:Linux 執行環境與 Flea 官方 binary/QML**:使用同架構的 Debian/glibc 環境及 Linux Bun,不能把 Android Bun 當作 Debian Bun。Flea binary 所需的 ELF loader、libc、libgcc 不能用退出成功的 stub 取代。從 Omarchy 套件來源取得 `flea-0.3.12-1` 對應架構的完整套件,保留其 `usr/bin/flea`、`usr/share/flea`、`usr/lib/flea` 和符號連結,解開到容器對應路徑;不要只複製 binary。套件管理器的完整桌面依賴不是本實驗的全部必要條件。此節從上述官方套件已解開、完整 buninu-browser 專案已放在 `/opt/buninu-browser` 開始;不以缺少官方檔案時自動產生假的 QML 補洞。
|
|
175
|
+
|
|
176
|
+
- **必要:Omarchy 的 Commons/Ui QML 模組**:不能以空目錄 stub,Theme 和控制項真的會用到。若尚未有模組,可直接取得已驗證的官方版本,不引用本機隔壁 checkout。只需要其 `shell/Commons`、`shell/Ui` 及套件既有連結,不必啟動 Omarchy/Hyprland。
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
git clone https://github.com/basecamp/omarchy.git /opt/omarchy-source
|
|
180
|
+
git -C /opt/omarchy-source checkout 3c7027db2a4fa9fa6a49d7af7f87c27ac48e677d
|
|
181
|
+
mkdir -p /usr/share/omarchy/shell
|
|
182
|
+
cp -a /opt/omarchy-source/shell/Commons /opt/omarchy-source/shell/Ui /usr/share/omarchy/shell/
|
|
183
|
+
ln -sfn shell /usr/share/omarchy/qs
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- **必要:`qs` 啟動入口,替代原生 Quickshell/Qt**:先準備獨立 helper 目錄並複製本專案的檔案。下列 `qs` 是 3 行 wrapper,轉交 `/opt/buninu-browser/lib/qml/qswayland`,不用安裝原生 Quickshell、QtQuick 或 QtMultimedia。若專案放在別處,修改 wrapper 最後一行即可。僅啟用 `qs`;不要一次把所有實驗 stub 都放進 PATH。
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
mkdir -p /usr/local/lib/flea-helpers /usr/local/bin
|
|
190
|
+
cp -a /opt/buninu-browser/test/fixtures/flea-helpers/. /usr/local/lib/flea-helpers/
|
|
191
|
+
chmod +x /usr/local/lib/flea-helpers/bin/*
|
|
192
|
+
ln -sfn /usr/local/lib/flea-helpers/bin/qs /usr/local/bin/qs
|
|
193
|
+
export PATH="/usr/local/bin:$PATH"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
- **必要:Wayland socket 與可寫入的 HOME/XDG 目錄**:這是實際 IPC,不能用空檔案 stub。Termux 啟動容器時以 `-b "$TMPDIR:/tmp"` 分享宿主 tmp;容器中使用 `XDG_RUNTIME_DIR=/tmp`、`WAYLAND_DISPLAY=wayland-buninu`。原生 Linux 則填 Land 實際使用的目錄與 socket 名稱。HOME 要能寫入設定和快取;不要把宿主所有 XDG 路徑直接帶進不可見的容器。
|
|
197
|
+
|
|
198
|
+
```sh
|
|
199
|
+
export XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-buninu
|
|
200
|
+
export XDG_CONFIG_HOME="$HOME/.config" XDG_DATA_HOME="$HOME/.local/share"
|
|
201
|
+
export XDG_STATE_HOME="$HOME/.local/state" XDG_CACHE_HOME="$HOME/.cache"
|
|
202
|
+
mkdir -p "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_STATE_HOME" "$XDG_CACHE_HOME"
|
|
203
|
+
test -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
- **必要:`shared-mime-info` 資料庫**:Flea 依 `/usr/share/mime` 的 `globs2`、aliases 和描述分類檔案;沒有它時 PNG、文字可能變成 Data,根本不啟動預覽。不能用成功退出的命令 stub。Debian 可用 `apt-get install --no-install-recommends shared-mime-info`,或把該套件的完整 `/usr/share/mime` 解到容器;不要只造一個空檔。加入後重啟 Flea。
|
|
207
|
+
常見的新副檔名(例如 `.jsonl`)可能仍沒有 MIME 定義,會被 Flea 判成 Data,而不呼叫上色工具。可補本專案的 MIME 定義(包含 `Dockerfile` 檔名及 `.cjs`、`.ini`、`.tsx`),再重啟 Flea;Dockerfile 已包含這兩步。一般規則為低優先序;`.tsx` 特別以優先序 60 覆蓋 Debian 的 Tiled tileset 分類,讓 TypeScript JSX 可上色,因此同副檔名的 Tiled 檔案也會先走文字預覽:
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
install -Dm644 test/fixtures/flea-helpers/source-mime.xml /usr/share/mime/packages/buninu-source.xml
|
|
211
|
+
update-mime-database /usr/share/mime
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
HTML 是另一條路徑:Flea 預設要求網頁渲染預覽,並非原始碼上色。在 Space 開啟的預覽按 `r` 切換 source 才會使用 bat/jsmdcui。原始碼上色不需要 HTML 截圖工具;rendered 模式仍需要 Flea 呼叫 `/usr/bin/qml6` 與內附的 Qt WebEngine HTML 預覽程式,這個實驗容器尚未提供。
|
|
215
|
+
|
|
216
|
+
- **實驗替代:`bat` 語法上色,透過 `bun i jsmdcui`**:Flea 要求 bat 的 realpath 位於 `/usr`,因此在獨立的 `/usr/local/lib/flea-helpers` 安裝,主專案不會新增 `node_modules`。`bat` wrapper 呼叫本專案附帶的 `bat.mjs`,它處理 Flea 的參數、stdin、行範圍與基本 ANSI 色碼,再使用 jsmdcui 真正上色。不能把 `bat` 直接連到 jsmdcui CLI,兩者參數不同。已驗證的 jsmdcui 原始版本為 0.19.2;新版本若變更內部模組,請改用 `bun i jsmdcui@0.19.2`。
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
cd /usr/local/lib/flea-helpers
|
|
220
|
+
bun i --backend=copyfile jsmdcui
|
|
221
|
+
ln -sfn /usr/local/lib/flea-helpers/bin/bat /usr/local/bin/bat
|
|
222
|
+
ln -sfn /usr/local/lib/flea-helpers/bin/glow /usr/local/bin/glow
|
|
223
|
+
printf 'const answer = 42;\n' | bat --color=always --style=plain --paging=never --file-name=sample.js -
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`glow` 是另附的 jsmdcui `--cat` 入口,方便手動讀文件;Flea 程式碼上色呼叫的是 `bat`。`--backend=copyfile` 避免 Android/proot 的硬連結限制;一般原生 Linux 可直接 `bun i jsmdcui`。安裝位置是獨立 helper 目錄,Dockerfile 也採用同樣方式。適配器只覆蓋 Flea 使用的 bat 參數,不是完整 bat 實作。 自動載入 jsmdcui 的全部語法定義,另補常見語言別名及 JSX、MTS/CTS、JSONC/JSON5/JSONL 等副檔名。`syntax-compat.mjs` 在 adapter 內轉換語法規則的 Go regex flags/字邊界,修正 Dockerfile、batch 等規則在 JavaScript 無法編譯的問題,不修改 npm 安裝內容。
|
|
227
|
+
|
|
228
|
+
[check-highlighting.mjs](../../test/fixtures/flea-helpers/check-highlighting.mjs) 會真正透過官方 Flea 後端,檢查每種格式以檔案路徑與 Markdown 語言名稱送入時都有非零顏色 role,並確認文字未被改寫。樣本列在 [highlight-cases.json](../../test/fixtures/flea-helpers/highlight-cases.json):JS/MJS/CJS/JSX、TS/TSX/MTS、Python、sh/zsh/fish、JSON/JSONC/JSON5/JSONL、YAML、TOML、INI/dotenv、HTML/XML、CSS/SCSS、SQL、C/C++/C#、Go、Rust、Java、Kotlin、Ruby、PHP、Lua、Perl、PowerShell、batch、Dockerfile、Makefile、CMake、Markdown、diff、Terraform、Vue、Svelte。這是沿用 jsmdcui 的語法規則,不是各語言的完整 parser;未知語言明確退回原文。
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
udocker run flea-qml bun /usr/local/lib/flea-helpers/check-highlighting.mjs
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
[check-preview.mjs](../../test/fixtures/flea-helpers/check-preview.mjs) 另用隔離設定開啟官方 Flea 的 JS、JSONL 與 HTML source 預覽(HTML 會按 `r` 切換),確認 UI 實際上色 並截圖到容器 `/tmp/flea-js-preview.png`;已目視確認關鍵字/運算子與數字顏色。可執行 `udocker run flea-qml bun /usr/local/lib/flea-helpers/check-preview.mjs` 重現,不影響目前 Land 視窗。
|
|
235
|
+
|
|
236
|
+
- **實驗替代:`bubblewrap`/`bwrap` 與 `prlimit`**:上色、縮圖等 helper 會經過沙箱;缺少 `bwrap` 或 `prlimit` 時,有些路徑連工具都不會呼叫。一般 Linux 優先保留真正的 bubblewrap。bunproot 實驗可選用本專案的 10 行 `bwrap`,吃掉已知參數、關閉 status fd,再直接執行 helper;不捏造 PID。這會取消 namespace/檔案系統隔離,但仍保留外層 `prlimit`;不能視為安全沙箱。Debian 的 `prlimit` 由 `util-linux` 提供,不用成功 stub 偷偷取消資源限制。
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
ln -sfn /usr/local/lib/flea-helpers/bin/bwrap /usr/local/bin/bwrap
|
|
240
|
+
command -v bwrap prlimit
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
[bwrap-real-filter](../../test/fixtures/flea-helpers/bin/bwrap-real-filter) 也已保存於本專案,只供重現先前「過濾參數後仍呼叫 `/usr/bin/bwrap-real`」的診斷;該路徑在 bunproot 的 fd readlink 仍失敗,**不要用它作為成功啟動步驟**。shell wrapper 本身仍需要 Debian 的 `/bin/sh`、Bash、`realpath`、`dirname`、`env` 等基本工具。
|
|
244
|
+
|
|
245
|
+
- **實驗替代:影片縮圖 `ffmpegthumbnailer`/`libffmpegthumbnailer.so.4`**:可以完全不安裝,改用本專案的 3 行 stub 和 4 行 `.thumbnailer`。它給每個註冊的影片 MIME 寫同一張不透明 1×1 PNG;沒有讀取影片,也不冒充解碼成功。官方 Flea 後端已實測回傳非空 `thumbed.file`,QML 因而不再顯示缺縮圖提示。播放仍由真正的 WASM 解碼器負責。複製後須重開 Flea;停用時刪除註冊檔,已生成的佔位縮圖仍可能留在快取。
|
|
246
|
+
|
|
247
|
+
```sh
|
|
248
|
+
install -Dm755 /opt/buninu-browser/test/fixtures/flea-thumbnail-stub/flea-thumbnail-stub /usr/local/bin/flea-thumbnail-stub
|
|
249
|
+
install -Dm644 /opt/buninu-browser/test/fixtures/flea-thumbnail-stub/flea-placeholder.thumbnailer /usr/share/thumbnailers/flea-placeholder.thumbnailer
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
- **可省略:FFmpeg/`ffprobe` 媒體資訊**:Flea 用 `ffprobe` 讀編碼、採樣率等;瀏覽器的 MP3/MP4 播放不呼叫它。沒有就保留未知資訊,不要編造時長、大小或編碼。最小方案是不安裝、不提供 stub;若之後需要完整資訊,再裝 `ffmpeg`。影片縮圖則是上一項的另一條路徑,單裝 ffmpeg 不等於註冊了縮圖工具。
|
|
253
|
+
|
|
254
|
+
- **播放與聲音:QtMultimedia、音訊服務、IdleInhibitor**:QtMultimedia 已由本專案 QML MediaPlayer/AudioOutput/VideoOutput 適配到原有瀏覽器播放器,不需要外部 Qt `.so`。出聲要有播放器可連到的 jspulse/PulseAudio `127.0.0.1:4713`;宿主執行 `bunx @drxiaozhi/jspulse --sles`(Android)或 `bunx @drxiaozhi/jspulse --alsa`(Linux ALSA)。假成功 stub 不會產生聲音,不要求出聲則可靜音。IdleInhibitor 只提示未實做,不阻止播放,不需要額外 stub。宿主音訊服務在容器網路下也必須可達。
|
|
255
|
+
|
|
256
|
+
- **剪貼板:Wayland、`wl-copy` 與 host 工具**:文字框的複製貼上由本專案與 Land 的 Wayland 剪貼板處理;Land 優先 xclip,再走既有平台 fallback,不需要為此安裝 Qt。Flea 的選單「Copy Path」/分享連結另外直接呼叫 `wl-copy`,不是同一接口;要用它就安裝 `wl-clipboard` 或提供真的能寫入同一剪貼板的 adapter。本專案沒有把空寫入包裝成成功的 wl-copy stub;不安裝時省略這些選單功能,不宣稱已複製。
|
|
257
|
+
|
|
258
|
+
- **可省略:`jq` JSON 美化**:它不是文字列表或播放器的啟動依賴。不裝時不要假裝回傳有效 JSON;需要完整 JSON 預覽時安裝 jq。本文的 jsmdcui 適配器負責上色,不是 jq 查詢語言替代品。
|
|
259
|
+
|
|
260
|
+
- **可省略:圖片外掛、PDF、Office 與 Markdown 圖表**:一般 PNG/JPEG 等走瀏覽器現有解碼,不需要 Qt 的 kimageformats/libheif;HEIC 等未支援格式不能靠 stub 得到真實圖片。QtQuick.Pdf/qt6-webengine 仍不能由安裝套件直接接到我們的 DOM runtime,缺少 QML 相容功能時保留未支援。LibreOffice 用於 Office 預覽,QuickJS-NG(`qjs`)用於數學/圖表 helper;不需要這些功能就不裝。不能只把 qjs 連到 bun,旗標與執行環境尚未適配。
|
|
261
|
+
|
|
262
|
+
- **可省略:垃圾桶、裝置、網路與桌面服務**:GLib/GIO、GVfs(含 AFC/MTP/gphoto2/NFS/SMB/DNSSD)、udisks2、usbmuxd、D-Bus,以及 Python/PyGObject、expect 等是相應桌面 helper 的依賴,不是本地檔案列表的前置服務。`gio trash`、掛載、卸載、解鎖不能用 `exit 0` 騙成功,否則會把未完成的操作呈現成完成;最小方案保留不可用,真的需要時安裝服務。原生 Flea 的 portal、FileManager1 與 MPRIS helper 不等於我們已提供完整 D-Bus 桌面。
|
|
263
|
+
|
|
264
|
+
- **可省略:外部開檔/終端機**:`gio open`/xdg-utils、desktop MIME 關聯、`xdg-terminal-exec` 與 Omarchy launcher 不影響 Flea 內建預覽。要讓按鈕真的開出程式,需要實際 launcher;`xdg-terminal-exec` 接收 `--dir=...`,不能直接連到不接受該旗標的命令。沒有時保留不可用;不要把「已啟動」假回覆給使用者。hicolor-icon-theme 是桌面安裝圖示的配套,不是我們的 DOM 播放依賴。
|
|
265
|
+
|
|
266
|
+
- **可省略:壓縮、轉檔與分享**:libarchive/`bsdtar`、7zip/`7z`、ImageMagick/`magick`、tailscale、dropbox-cli、zoxide 分別提供壓縮操作、圖片轉換、分享與常用目錄排序。沒有就不啟用這些功能,不用假成功 stub;涉及寫入的操作尤其不能只回傳 0。若測試環境需要一個明確失敗的命令,可複製 [unsupported](../../test/fixtures/flea-helpers/bin/unsupported) 並取所需名稱;它只有 3 行,印出未支援並回傳 1,不是完整協定替代品。
|
|
267
|
+
|
|
268
|
+
- **最後啟動與驗收**:前述必要檔案、MIME、qs、bat/jsmdcui,以及需要時的 bwrap/縮圖替代都準備好後,從同一容器 shell 啟動。`QSG_RHI_BACKEND=opengl` 僅跳過 Flea 的原生 Vulkan 探測,不代表瀏覽器開啟 GPU。這些指令沒有啟動第二個 Land。
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
command -v bun flea qs bat prlimit
|
|
272
|
+
test -r /usr/share/mime/globs2
|
|
273
|
+
test -d /usr/share/omarchy/qs/Commons
|
|
274
|
+
env PATH="/usr/local/bin:$PATH" QSG_RHI_BACKEND=opengl flea --gui "$HOME"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
驗收:先看一般檔案列表,用滑鼠開啟資料夾,或用上下方向鍵選取資料夾後按右方向鍵進入,找到 JS/TXT/MP4 範例檔案;程式碼應有色、影片先顯示固定色縮圖,按播放後顯示真實影片。若失敗,先區分缺少分類資料、helper 未找到、沙箱失敗、播放錯誤;不能把已知的佔位縮圖結果當成所有外部功能都支援。
|
|
278
|
+
|
|
279
|
+
## Termux udocker Debian experiment
|
|
280
|
+
|
|
281
|
+
Verified on 2026-10-23: the official **Flea 0.3.12-1 aarch64** package runs
|
|
282
|
+
through `qswayland` in a separate Debian 13 (trixie) container and displays on
|
|
283
|
+
an **already running Land outside the container**. The container was started
|
|
284
|
+
from a native Termux shell via `jsgotty --client`, not inside the development
|
|
285
|
+
Debian proot.
|
|
286
|
+
|
|
287
|
+
The retained container is named **`flea-qswayland`**, under
|
|
288
|
+
`~/.udocker/containers/flea-qswayland/ROOT` in Termux. Its ID is
|
|
289
|
+
`82ef2c52-a491-4723-9604-855f22bd92d5`. It was created using
|
|
290
|
+
`udocker run -b "$TMPDIR:/tmp" debian`, then named with `udocker rename`.
|
|
291
|
+
|
|
292
|
+
#### Files copied into the container
|
|
293
|
+
|
|
294
|
+
| Container location | Contents |
|
|
295
|
+
| --- | --- |
|
|
296
|
+
| `/usr/bin/flea`, `/usr/share/flea`, and other package paths | Extracted official Flea package, preserving symlinks |
|
|
297
|
+
| `/opt/buninu-browser` | Browser working tree, excluding `.git` and `node_modules` |
|
|
298
|
+
| `/usr/local/bin/bun` | Existing Linux aarch64 glibc Bun 1.4.4 executable |
|
|
299
|
+
| `/usr/share/omarchy/shell/Commons` and `/usr/share/omarchy/shell/Ui` | Existing Omarchy QML reference modules |
|
|
300
|
+
|
|
301
|
+
Copying only Flea and the browser is insufficient: Debian needs the Bun runtime,
|
|
302
|
+
and Flea's QML package links `Commons`/`Ui` to `/usr/share/omarchy/shell/`.
|
|
303
|
+
No additional apt/npm packages or native Qt/Quickshell runtime were installed.
|
|
304
|
+
The Linux Bun executable is used inside Debian, not the Android Bun executable.
|
|
305
|
+
|
|
306
|
+
For named QML imports, `/usr/share/omarchy/qs` links to `shell`.
|
|
307
|
+
The executable `/usr/local/bin/qs` is this wrapper:
|
|
308
|
+
|
|
309
|
+
```sh
|
|
310
|
+
#!/bin/sh
|
|
311
|
+
export QML_IMPORT_PATH="/usr/share/omarchy${QML_IMPORT_PATH:+:$QML_IMPORT_PATH}"
|
|
312
|
+
exec /usr/local/bin/bun /opt/buninu-browser/lib/qml/qswayland "$@"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
To reopen the prepared container, run **from Termux**:
|
|
316
|
+
|
|
317
|
+
```sh
|
|
318
|
+
udocker run -b "$TMPDIR:/tmp" flea-qswayland
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Then run **inside the container**:
|
|
322
|
+
|
|
323
|
+
```sh
|
|
324
|
+
env XDG_RUNTIME_DIR=/tmp \
|
|
325
|
+
WAYLAND_DISPLAY=wayland-buninu \
|
|
326
|
+
QSG_RHI_BACKEND=opengl \
|
|
327
|
+
flea --gui /root
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
The bind exposes Termux's Wayland socket as `/tmp/wayland-buninu`; Land itself
|
|
331
|
+
stays on the host. `QSG_RHI_BACKEND=opengl` bypasses Flea's native Vulkan probe
|
|
332
|
+
and does not enable GPU rendering in our frontend. Flea finds `qs` on the
|
|
333
|
+
container's default PATH and starts its real `--backend` child.
|
|
334
|
+
|
|
335
|
+
Observed result: the host Land screenshot shows the container's `/root/Documents`
|
|
336
|
+
and `/root/hello.txt`. This verifies launch and basic file listing, not optional
|
|
337
|
+
Trash, mounts, previews, or all external-tool integrations. Notes are retained in
|
|
338
|
+
`/root/FLEA-TEST.txt`; the test log is `/tmp/flea-udocker.log` on the shared tmp.
|
|
339
|
+
The copied browser is a snapshot; later repository changes require copying again.
|
|
340
|
+
|
|
341
|
+
During image extraction, Android rejected the hardlink for
|
|
342
|
+
`/usr/bin/perl5.40.1`; this missing alias was repaired by copying `/usr/bin/perl`
|
|
343
|
+
to that path. No other extraction error was reported in this run.
|
|
344
|
+
|
|
345
|
+
The container now also contains a copy of the development Debian's complete
|
|
346
|
+
`/usr/share/mime` database (including `globs2`, aliases and type descriptions).
|
|
347
|
+
Flea uses it to classify filenames; without it, even `.txt` and `.png` can appear
|
|
348
|
+
as generic Data and never reach their preview components. Restart Flea after
|
|
349
|
+
copying. Media helpers and QML multimedia/PDF support remain separate requirements.
|
|
350
|
+
|
|
351
|
+
容器另已複製目前 Debian 完整的 `/usr/share/mime` 資料庫,包含 `globs2`、別名
|
|
352
|
+
與類型描述。缺少它時,文字與圖片也可能被歸類為 Data,無法進入對應預覽;
|
|
353
|
+
複製後需重開 Flea。影音工具與 QML 影音/PDF 相容仍是另外的需求。
|
|
354
|
+
|
|
355
|
+
### glow / bat compatibility experiment (2026-10-24)
|
|
356
|
+
|
|
357
|
+
The retained `flea-qswayland` container contains an unchanged copy of
|
|
358
|
+
`buninu/bin/glow.sh` and the entire bundled `apps/jsmdcui` at
|
|
359
|
+
`/usr/local/lib/buninu-glow`. `/usr/local/bin/glow` points to `bin/glow.sh`;
|
|
360
|
+
`bat` points to `bin/bat.sh`, which runs `bat.mjs`. The adapter accepts Flea's
|
|
361
|
+
bat flags, highlights stdin with jsmdcui, selects the requested line range,
|
|
362
|
+
and emits basic ANSI colors understood by Flea's role parser.
|
|
363
|
+
|
|
364
|
+
At the user's request, container `bin/bwrap.sh` temporarily **bypasses bwrap**:
|
|
365
|
+
it consumes the known sandbox options and executes the helper directly. It
|
|
366
|
+
closes the JSON status fd without inventing a sandbox PID. The outer Flea
|
|
367
|
+
`prlimit` still applies, but bwrap filesystem/namespace isolation does not.
|
|
368
|
+
The real-bwrap filter is retained as `bin/bwrap-real-filter.sh`; that path
|
|
369
|
+
currently fails on fd readlink after pivot_root under bunproot.
|
|
370
|
+
No new native dependency was installed.
|
|
371
|
+
|
|
372
|
+
Verified through native Termux → bunproot → Debian → official Flea 0.3.12
|
|
373
|
+
backend: `/root/flea-color-probe.mjs` returned `state: "styled"` with keyword,
|
|
374
|
+
number and comment roles 3, 1 and 4, using the actual helper subprocess.
|
|
375
|
+
This verifies backend highlighting, not a new visual inspection of Flea's UI.
|
|
376
|
+
`/root/glow-flea-probe.sh` tests the adapter directly and with Flea's flags;
|
|
377
|
+
`/root/flea-bwrap-probe.sh` retains the real-bwrap reproduction.
|
|
378
|
+
|
|
379
|
+
同一容器完整保留原始 glow 與 jsmdcui;`glow` 指向原始腳本,`bat` 改指向
|
|
380
|
+
`bin/bat.sh`,透過 `bat.mjs` 適配 Flea 的參數、stdin、行範圍和基本 ANSI 顏色。
|
|
381
|
+
依使用者要求,實驗用 `bin/bwrap.sh` 暫時直接執行 helper,關閉狀態 fd 而不
|
|
382
|
+
捏造 PID;保留外層 prlimit,但沒有 bwrap 的檔案系統與 namespace 隔離。
|
|
383
|
+
原本呼叫真正 bwrap 的版本保留為 `bin/bwrap-real-filter.sh`,仍卡在 bunproot
|
|
384
|
+
切換根目錄後的 fd readlink。未安裝新的原生依賴。
|
|
385
|
+
|
|
386
|
+
原生 Termux → bunproot → Debian → 官方 Flea 0.3.12 backend 實測回傳
|
|
387
|
+
`state: "styled"`,關鍵字、數字與註解角色分別為 3、1、4。這是實際執行
|
|
388
|
+
helper 的後端驗證,尚非本輪 Flea 畫面的視覺驗證;容器 `/root` 保留上述腳本。
|
|
389
|
+
|
|
390
|
+
## Flea: current verified scope
|
|
391
|
+
|
|
392
|
+
The unchanged `ui/boot/shell.qml` from Flea revision
|
|
393
|
+
`f21789e56cc4b0877caa3156fff7bce52a8dd9c2` runs with real Flea Theme and Omarchy
|
|
394
|
+
Commons/Ui imports from revision `3c7027db2a4fa9fa6a49d7af7f87c27ac48e677d`.
|
|
395
|
+
Tests use isolated HOME/XDG directories. They do not inject fake backend replies.
|
|
396
|
+
|
|
397
|
+
Verified against those sources:
|
|
398
|
+
|
|
399
|
+
- Main window startup, settings opened by the real toolbar, Display/Keys tabs,
|
|
400
|
+
and Escape closing the panel.
|
|
401
|
+
- Ctrl-L path editing, replacement of selected text, and Escape cancellation.
|
|
402
|
+
- The real keyboard help sheet and Add network share dialog, including typing a
|
|
403
|
+
host and switching SMB to SFTP. Connecting/mounting is **not** tested.
|
|
404
|
+
- Original Row/GridTile components render metadata and react to changed input;
|
|
405
|
+
GridTile retains its two-line filename caption. These use test input data, not
|
|
406
|
+
a backend replacement.
|
|
407
|
+
- Real text and CSV files through `PreviewText`; Markdown through the original
|
|
408
|
+
`MarkdownWorker.js` and its `Qt.include` dependencies on a real worker thread.
|
|
409
|
+
- SVG/PNG preview, zoom and fit through the original `PreviewImage.qml`.
|
|
410
|
+
- SettingsRuler, DialogButton and DialogField behavior compared with an existing
|
|
411
|
+
Quickshell binary, without reading its implementation source.
|
|
412
|
+
- Flea StableModel resize/warm behavior and virtualized delegates; a separate
|
|
413
|
+
range-model test represents 100 million rows without creating that many DOM nodes.
|
|
414
|
+
- A separate real Wayland socket test opens Settings, closes it with Escape, and
|
|
415
|
+
closes the native window with Land's Super-W. It owns a separate compositor.
|
|
416
|
+
|
|
417
|
+
The source inventory parses 239 QML files and compiles 231 of 235 top-level UI
|
|
418
|
+
components. The four remaining compile blockers are QtQuick.Pdf (PdfViewer,
|
|
419
|
+
PreviewPdf) and AnimatedImage (PreviewAnimation).
|
|
420
|
+
Dynamic loaders defer some of these until the associated feature is opened.
|
|
421
|
+
|
|
422
|
+
**Full Flea file management is not yet supported or validated.** The original
|
|
423
|
+
73-test run used no backend; the later official-binary tests above cover real
|
|
424
|
+
listing/navigation and directory updates. Without `FLEA_BIN`, the main app still
|
|
425
|
+
displays its own unavailable state. Copying/moving/deleting, mounts, clipboard
|
|
426
|
+
integration and PDF/media remain outside this result.
|
|
427
|
+
A compile inventory is not an end-to-end application test.
|
|
428
|
+
|
|
429
|
+
```sh
|
|
430
|
+
# Existing, unchanged sibling checkouts; no download or installation is performed.
|
|
431
|
+
bun test/manual-flea-application.js
|
|
432
|
+
|
|
433
|
+
# Optional: supply an already installed real backend.
|
|
434
|
+
FLEA_BIN=/absolute/path/to/flea bun test/manual-flea-application.js
|
|
435
|
+
|
|
436
|
+
# Headless application, preview, worker and compile inventory tests.
|
|
437
|
+
BUNINU_FLEA_ROOT=../flea BUNINU_OMARCHY_ROOT=/opt/omarchy-source \
|
|
438
|
+
bun test test/qml-flea-app.test.js test/qml-flea-previews.test.js \
|
|
439
|
+
test/qml-flea-compile.test.js test/qml-flea-rows.test.js test/qml-worker.test.js
|
|
440
|
+
|
|
441
|
+
# Own isolated compositor; does not affect an existing Land session.
|
|
442
|
+
BUNINU_FLEA_ROOT=../flea BUNINU_OMARCHY_ROOT=/opt/omarchy-source \
|
|
443
|
+
BUNINU_QML_WAYLAND_TEST=1 bun test test/qml-flea-wayland.test.js
|
|
444
|
+
|
|
445
|
+
# Optional genuine Debian arm64 Quickshell binary already extracted elsewhere.
|
|
446
|
+
BUNINU_QS_ROOT=/path/to/sid/root bun test test/qml-quickshell-controls.test.js \
|
|
447
|
+
test/qml-quickshell-settings.test.js
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Validation on 2026-10-23 (Bun 1.4.4 canary, Debian proot): all 73 QML tests
|
|
451
|
+
passed with the Flea, Omarchy, real Quickshell and isolated Wayland options enabled
|
|
452
|
+
(211 assertions). The removal check separately passed 9 ordinary browser tests
|
|
453
|
+
(71 assertions) after deleting all 14 integration blocks and `lib/qml`.
|
|
454
|
+
|
|
455
|
+
The manual app runner uses the current Wayland socket and creates temporary
|
|
456
|
+
HOME/config/state/data/cache directories. It never writes personal Flea settings.
|
|
457
|
+
Close the window to remove those directories. See its `--help` for paths/options.
|
|
458
|
+
|
|
459
|
+
## Imports and language
|
|
460
|
+
|
|
461
|
+
- Relative directories, implicit sibling components, named module directories,
|
|
462
|
+
and qualified imports. Local modules additionally search `QML_IMPORT_PATH`.
|
|
463
|
+
- `qmldir` component entries, singleton/internal entries and version selection:
|
|
464
|
+
same major, highest available minor not above the requested version.
|
|
465
|
+
- Per-instance IDs, inheritance, properties, required/readonly properties,
|
|
466
|
+
writable aliases, default/named content slots, methods and signal declarations.
|
|
467
|
+
- Typed QML functions, inline components, grouped properties, `Behavior on`,
|
|
468
|
+
statement handlers and checked QML `as` casts. Types do not implement all Qt
|
|
469
|
+
conversion/coercion rules.
|
|
470
|
+
- JS imports, nested `.import`, and `.pragma library`. Library dependencies share
|
|
471
|
+
document scope; ordinary scripts belong to the component instance. Generated
|
|
472
|
+
names avoid application variables. QML `String.arg()` is translated without
|
|
473
|
+
changing JavaScript's frozen/shared prototypes.
|
|
474
|
+
- Singleton allocation precedes binding evaluation, including mutually referring
|
|
475
|
+
Theme/Glass and Color/Style objects. Reload creates fresh singleton state.
|
|
476
|
+
- `Component`, `Loader`, local `Qt.createComponent`, `Qt.binding`, and `Binding`.
|
|
477
|
+
Factories make ordinary DOM and dispose instance effects, listeners and timers.
|
|
478
|
+
Imperative assignments detach bindings; aliases forward writes and can rebind.
|
|
479
|
+
|
|
480
|
+
Limits: 256 KiB per imported source, 4 MiB combined source, import depth 48,
|
|
481
|
+
1,024 local or 128 remote resource requests, 2,000 statically expanded objects.
|
|
482
|
+
Live runtime limits are 30,000 local or 2,000 remote objects. Local Flea settings
|
|
483
|
+
prebuilds require the higher local limit. Import cycles, native Qt plugins and
|
|
484
|
+
unsupported declarations are explicit diagnostics. Module version syntax is not
|
|
485
|
+
an assertion that every API from that Qt version exists.
|
|
486
|
+
|
|
487
|
+
No version-suffixed module directories, qmldir dependency/prefer directives,
|
|
488
|
+
`.mjs` imports, remote dynamic components or Qt native plugin loading.
|
|
489
|
+
|
|
490
|
+
## Rendering and interaction
|
|
491
|
+
|
|
492
|
+
Items map to DOM/CSS: Rectangle, Text/Label, TextInput/TextEdit/TextField, Button,
|
|
493
|
+
MouseArea, pointer handlers, Image, Row/Column/Grid/Flow, RowLayout/ColumnLayout,
|
|
494
|
+
Flickable, ListView/GridView and basic Shape paths.
|
|
495
|
+
|
|
496
|
+
- Anchors include sides, centers, margins and baselines. Positioners respect
|
|
497
|
+
visible children and padding. Basic layouts support preferred/min/max/fill
|
|
498
|
+
sizes and alignment; full Qt layout negotiation is not implemented.
|
|
499
|
+
- Text measurement uses the existing canvas text API and a bounded cache.
|
|
500
|
+
PlainText is literal. Styled/Rich/Auto text builds inert restricted DOM;
|
|
501
|
+
local Markdown uses Bun's Markdown renderer. Line counts and wrapped filename captions are supported. Mixed-format metrics
|
|
502
|
+
and multiline ellipsis are approximate, and rich-text embedded images are unsupported.
|
|
503
|
+
- SVG-shaped icons reuse the browser's inline SVG painter. ShapePath linear
|
|
504
|
+
gradients use an ordinary page canvas on the existing CanvasKit instance:
|
|
505
|
+
no image encode/decode or raster readback is introduced for that path.
|
|
506
|
+
- Raster Image uses the normal browser decoder. Basic file/data/HTTP SVG images
|
|
507
|
+
use inert inline SVG DOM instead of a PNG conversion. SVG text, gradients,
|
|
508
|
+
filters, masks and external resources are not implemented by that path.
|
|
509
|
+
`sourceSize`, EXIF autoTransform, tiled fill and precise Qt decode/cache policy
|
|
510
|
+
are not complete; raster size remains governed by the existing browser decoder.
|
|
511
|
+
- Text selection/editing, accepted signals, focus, Keys.forwardTo and key
|
|
512
|
+
acceptance work with actual DOM events. Editing keys do not trigger ancestor
|
|
513
|
+
shortcuts; Escape can propagate. Hidden prebuilt controls cannot steal focus. FocusScope ancestors track active
|
|
514
|
+
focus and can restore their last active child. Menu/AltGr keys and mouse
|
|
515
|
+
back/forward buttons retain distinct codes. Text controls paint a blinking
|
|
516
|
+
caret (500 ms per phase); Left/Right collapse a selection to its corresponding
|
|
517
|
+
edge, and Shift extends it. Home/End and Ctrl+A use the same selection state.
|
|
518
|
+
Selection painting, caret blinking and keyboard editing now use the common
|
|
519
|
+
HTML input/textarea implementation. QML only maps its properties, methods and
|
|
520
|
+
signals. Ctrl+C/X/V and copy()/cut()/paste() transfer text on demand; Wayland
|
|
521
|
+
uses wl_data_device and never polls the external clipboard. Shift+Up/Down
|
|
522
|
+
extends textarea selection across explicit lines; wrapped visual-line movement
|
|
523
|
+
is not yet implemented.
|
|
524
|
+
- Rejected MouseArea presses fall through to the next painted item; the same
|
|
525
|
+
recipient receives the release/click, so overlays can decline a row press.
|
|
526
|
+
Replacing a ListView/GridView model resets its scroll to the origin, while
|
|
527
|
+
updating the same model preserves the current position.
|
|
528
|
+
- TapHandler supports click/release and basic double taps; HoverHandler observes
|
|
529
|
+
pointer movement without intercepting underlying controls. Point/Drag handlers
|
|
530
|
+
and DropArea are partial DOM-event adapters, not Qt gesture arbitration or
|
|
531
|
+
complete native drag-and-drop.
|
|
532
|
+
- ListModel, DelegateModel/Group and virtualized views instantiate a bounded
|
|
533
|
+
visible/cache range, with pooling/reuse and synchronous forceLayout. ListView
|
|
534
|
+
positions measured delegates by their individual heights (widths horizontally),
|
|
535
|
+
and updates following rows when a delegate grows. Unseen rows use estimated
|
|
536
|
+
extents; only visited measurements are stored. Sections, full highlight behavior
|
|
537
|
+
and model role semantics remain limited. At most 500 visible delegates are
|
|
538
|
+
created per view layout.
|
|
539
|
+
- XmlListModel supports simple element paths and attribute/element roles such as
|
|
540
|
+
XBEL bookmarks; it is not an XPath implementation.
|
|
541
|
+
- Timer, basic numeric/property/sequence/parallel animations, Behavior and
|
|
542
|
+
FrameAnimation use the page event/animation loop. Window frame signals are
|
|
543
|
+
page-loop signals, not a guarantee of native Wayland presentation timing.
|
|
544
|
+
|
|
545
|
+
Local QML supports the ShaderEffectSource subset used by Flea: sourceItem,
|
|
546
|
+
sourceRect, textureSize, hideSource, live, scheduleUpdate and
|
|
547
|
+
scheduledUpdateCompleted. Its canvas holds a frozen image when live is false;
|
|
548
|
+
explicit updates and initial capture notify only after pixels are drawn.
|
|
549
|
+
Live updates coalesce DOM mutations into a single animation-frame capture;
|
|
550
|
+
there is no perpetual capture/poll loop when the source is unchanged. Arbitrary
|
|
551
|
+
canvas/video bitmap changes without DOM mutations are not yet live invalidations.
|
|
552
|
+
Multiple texture consumers reference-count a source; hideSource suppresses its
|
|
553
|
+
main-scene painting while preserving layout/input, and teardown restores it.
|
|
554
|
+
A referenced invisible QML source retains layout for capture. Its own opacity and
|
|
555
|
+
placement transform do not affect the texture root. A display:none ancestor is
|
|
556
|
+
still a limitation of retained-layout capture.
|
|
557
|
+
|
|
558
|
+
ShapePath.fillItem accepts ShaderEffectSource and clips its canvas to PathSvg or
|
|
559
|
+
PathRectangle, including per-corner radii. General Item fillItem, custom shaders,
|
|
560
|
+
recursive feedback, mipmaps and multisampling are not implemented. Window's
|
|
561
|
+
page-loop afterSynchronizing runs after pending texture captures; it is not a
|
|
562
|
+
native Wayland presentation timestamp.
|
|
563
|
+
|
|
564
|
+
Validation (no Land required):
|
|
565
|
+
|
|
566
|
+
```sh
|
|
567
|
+
bun test test/qml-textures.test.js test/qml-canvas-dom.test.js
|
|
568
|
+
# With BUNINU_FLEA_ROOT, BUNINU_OMARCHY_ROOT and FLEA_BIN configured above:
|
|
569
|
+
bun test test/qml-flea-textures.test.js test/qml-flea-preview-backend.test.js
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
These tests close their browser/backend in finally blocks. They check frozen
|
|
573
|
+
pixels, explicit/live updates, idle capture counts, source restoration, original
|
|
574
|
+
Flea hold/release and rounded masking, and actual text-to-text-to-PNG Quick Look
|
|
575
|
+
navigation. Preview screenshots are written to `/tmp/flea-real-preview-*.png`.
|
|
576
|
+
|
|
577
|
+
### Local QML DOM images
|
|
578
|
+
|
|
579
|
+
In local `file:` QML's dedicated host renderer, `ctx.drawImage(element, ...)`
|
|
580
|
+
also accepts a connected DOM element with a laid-out block box. All three
|
|
581
|
+
ordinary drawImage argument forms reuse canvas positioning, source cropping,
|
|
582
|
+
scaling, transforms and alpha. This is an internal QML extension, not a web API:
|
|
583
|
+
ordinary HTML (including local HTML/host mode) and remote QML do not enable it.
|
|
584
|
+
The capability is tracked outside page-writable globals.
|
|
585
|
+
|
|
586
|
+
The existing painter draws only the selected render subtree into a temporary
|
|
587
|
+
CanvasKit surface; siblings and ancestor opacity/clips are excluded. The source's
|
|
588
|
+
own styles, internal stacking, text and nested canvases use normal browser
|
|
589
|
+
painting. The snapshot uses the source border-box dimensions at one pixel per
|
|
590
|
+
CSS pixel and stays frozen until another draw. It does not modify the source DOM.
|
|
591
|
+
Images stay native to the same WASM CanvasKit instance: no PNG/base64 or pixel
|
|
592
|
+
readback is needed, and the temporary image/surface are released after use.
|
|
593
|
+
|
|
594
|
+
This initial path does not capture detached, display:none or inline-only sources,
|
|
595
|
+
iframes, or a subtree containing the destination canvas. Source visibility is
|
|
596
|
+
still governed by CSS for ordinary DOM snapshots; referenced QML texture
|
|
597
|
+
sources use the dedicated capture semantics described above. Captures are limited to 8192 pixels per side and 16,777,216 total pixels.
|
|
598
|
+
Cross-origin image/tainted-canvas resources propagate canvas readback restrictions;
|
|
599
|
+
unknown image origins are treated conservatively.
|
|
600
|
+
|
|
601
|
+
Run `bun test test/qml-canvas-dom.test.js` for pixel, isolation and resource-lifetime
|
|
602
|
+
checks. The removal check also strips the canvas adapter.
|
|
603
|
+
|
|
604
|
+
## Local host services and isolation
|
|
605
|
+
|
|
606
|
+
Local `file:` QML automatically uses a dedicated host renderer with application
|
|
607
|
+
HOME, PATH and XDG environment. This is executable local application code with Bun
|
|
608
|
+
access, not sandboxed web content. Reload starts a fresh renderer. Navigating back
|
|
609
|
+
to ordinary HTML swaps to the normal renderer, even in the same directory.
|
|
610
|
+
HTTP(S) QML stays isolated and cannot import local files or access these services.
|
|
611
|
+
Explicit `--dangerously-allow-host-js` retains its existing all-pages meaning.
|
|
612
|
+
|
|
613
|
+
`host.js` supplies real Process execution/stdin/streaming stdout/stderr,
|
|
614
|
+
FileView reads/watches/writes, local component loading and WorkerScript.
|
|
615
|
+
FileView atomic writes use a temporary sibling plus rename, and `saved` follows
|
|
616
|
+
completion; this is not an fsync durability guarantee. `waitForJob` flushes a
|
|
617
|
+
pending write. WorkerScript runs separately with bounded local `Qt.include`
|
|
618
|
+
loading; no backend replies are substituted. Resources stop on disposal.
|
|
619
|
+
|
|
620
|
+
LoggingCategory filters the available levels, not the complete Qt logging-rule
|
|
621
|
+
language. IpcHandler currently registers an in-page dispatch table; it does not
|
|
622
|
+
implement Quickshell's Unix IPC protocol. Live Hyprland services and GlassTagger
|
|
623
|
+
are not supported. `Qt.openUrlExternally` invokes the existing local `xdg-open`.
|
|
624
|
+
|
|
625
|
+
## Implementation map
|
|
626
|
+
|
|
627
|
+
- `format.js`: MIME/path recognition only, safe in the controller.
|
|
628
|
+
- `parser.js`: QML grammar with the already vendored MIT Acorn for JavaScript.
|
|
629
|
+
- `loader.js`: bounded shared async/sync import resolver.
|
|
630
|
+
- `document.js`: DOM factories, scope/alias resolution and hygienic JS generation.
|
|
631
|
+
- `reactive.js`: dependency tracking, lazy dirty reads and batched updates.
|
|
632
|
+
- `runtime.js`: properties, lifecycle, bindings, layout, input and services.
|
|
633
|
+
- `models.js`: list/range/XML models and virtualized views.
|
|
634
|
+
- `text.js`: inert rich-text DOM and plain-text measurement input.
|
|
635
|
+
- `shapes.js`, `images.js`: existing SVG/canvas/raster rendering adapters.
|
|
636
|
+
- `host.js`, `worker-thread.js`: local-only capabilities and worker execution.
|
|
637
|
+
|
|
638
|
+
## Removal / integration boundaries
|
|
639
|
+
|
|
640
|
+
All integration outside this directory has removable blocks, separated from
|
|
641
|
+
surrounding code by blank lines:
|
|
642
|
+
|
|
643
|
+
```js
|
|
644
|
+
// qml handle begin: purpose
|
|
645
|
+
// integration block
|
|
646
|
+
// qml handle end
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
```sh
|
|
650
|
+
rg -n 'qml handle' lib
|
|
651
|
+
bun test/manual-qml-removal.js
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
Existing integrations are in `lib/document-types.js`,
|
|
655
|
+
`lib/renderer/page-renderer.js`, `lib/headless-shell.js`, `lib/renderer/host.js`
|
|
656
|
+
`lib/renderer/main.js`, `lib/renderer/canvas-2d.js`, `lib/render-tree/index.js`, and `frontends/wayland/index.js`. Delete the marked blocks and `lib/qml`, plus its
|
|
657
|
+
tests/fixtures, to remove QML. Ordinary `let isHtml`, `let parsed`, `parsed ??=`,
|
|
658
|
+
renderer acquisition callbacks and default environments remain valid without
|
|
659
|
+
replacement statements. The removal test does this in a temporary copy and runs
|
|
660
|
+
ordinary renderer/navigation/headless tests. Wayland clipboard transport lives in `frontends/wayland/clipboard.js` and is
|
|
661
|
+
shared by ordinary pages. The optional QML HTTP clipboard bridge starts only
|
|
662
|
+
when navigating to local QML. Navigation guards discard stale renderer results
|
|
663
|
+
for all pages; neither common feature depends on QML.
|
|
664
|
+
|
|
665
|
+
Additional isolated checks:
|
|
666
|
+
|
|
667
|
+
```sh
|
|
668
|
+
bun test/manual-without-qml.js
|
|
669
|
+
bun test/manual-casty-without-qml.js /path/printed/by/the/first/test/buninu-browser
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
The first checks ordinary editing/clipboard/Wayland tests after removing QML,
|
|
673
|
+
and compares the original and stripped headless screenshots byte for byte.
|
|
674
|
+
The second drives actual Casty through a PTY, with an isolated xclip/OSC 52
|
|
675
|
+
clipboard and a minimal Kitty file-transfer peer. It checks selection,
|
|
676
|
+
copy/cut/paste, caret movement/blinking, navigator.clipboard readText/writeText,
|
|
677
|
+
denied reads without user activation, and raw BGRA frame delivery. It does not
|
|
678
|
+
modify the system clipboard or represent a test of every navigator API.
|
|
679
|
+
|
|
680
|
+
## References and provenance
|
|
681
|
+
|
|
682
|
+
Adjacent optional references, none a runtime dependency:
|
|
683
|
+
|
|
684
|
+
- [qmlweb-parser](https://github.com/qmlweb/qmlweb-parser), BSD-2-Clause.
|
|
685
|
+
- [qmlweb](https://github.com/qmlweb/qmlweb), MIT.
|
|
686
|
+
- [tree-sitter-qmljs](https://github.com/yuja/tree-sitter-qmljs), MIT.
|
|
687
|
+
- [qmlcore](https://github.com/pureqml/qmlcore), MIT.
|
|
688
|
+
|
|
689
|
+
Earlier import resolution consulted qmlweb's per-file contexts and directory
|
|
690
|
+
lookup; no qmlweb runtime was copied. This round uses Flea/Omarchy's MIT QML as
|
|
691
|
+
application inputs, public Qt API descriptions, and genuine Quickshell binary
|
|
692
|
+
behavior. No Quickshell implementation source was read or copied.
|
|
693
|
+
API behavior was checked against the public Qt documentation for
|
|
694
|
+
[Text](https://doc.qt.io/qt-6/qml-qtquick-text.html),
|
|
695
|
+
[focus scopes](https://doc.qt.io/qt-6/qtquick-input-focus.html),
|
|
696
|
+
[String.arg](https://doc.qt.io/qt-6/qml-string.html) and
|
|
697
|
+
[key/button enums](https://doc.qt.io/qt-6/qt.html).
|
|
698
|
+
|
|
699
|
+
Fixture provenance and bundled licenses are in
|
|
700
|
+
`test/fixtures/qml/flea-theme/README.md`.
|
|
701
|
+
|
|
702
|
+
## 中文說明
|
|
703
|
+
|
|
704
|
+
這是直接把 QML 編譯成既有 DOM、CSS、JS 的實驗,不產生 HTML,不保留另一棵
|
|
705
|
+
QML 元件樹,也不新增 Qt 或原生依賴。本輪程式集中在 `lib/qml`,測試在 `test`;
|
|
706
|
+
QML 外部接入使用 `qml handle begin/end` 區塊,可以整段刪除,不必補回程式。
|
|
707
|
+
一般 Wayland 剪貼簿位於 `frontends/wayland/clipboard.js`,普通網頁也共用;
|
|
708
|
+
QML 專用 HTTP 橋接只在導航至本地 QML 時啟動。導航期間忽略過期 renderer 結果
|
|
709
|
+
的保護屬於通用功能,不依賴 QML。
|
|
710
|
+
|
|
711
|
+
執行 `bun test/manual-without-qml.js` 可建立移除 QML 的獨立副本,
|
|
712
|
+
測試普通網頁編輯、剪貼簿與 Wayland,並逐位元組比較原版和副本的截圖。
|
|
713
|
+
再將輸出的副本路徑傳給 `bun test/manual-casty-without-qml.js 路徑`,
|
|
714
|
+
可經真正 Casty PTY 驗證選取、複製/剪下/貼上、遊標移動與閃爍、
|
|
715
|
+
navigator.clipboard 讀寫、無使用者操作時拒絕讀取,以及 BGRA 檔案傳輸。
|
|
716
|
+
測試使用隔離的 xclip/OSC 52 剪貼簿,不影響系統內容;不表示全部 navigator API 都經過測試。
|
|
717
|
+
|
|
718
|
+
本地 `file:` QML 的專用 host renderer 現在允許 `ctx.drawImage(DOM元素, …)`,
|
|
719
|
+
沿用三種 drawImage 呼叫形式、縮放、裁切及 canvas 透明度/變換。
|
|
720
|
+
能力由內部記錄控制,普通 HTML(包含本地 HTML/host 模式)與遠端 QML 不啟用。
|
|
721
|
+
指定子樹由既有 painter 畫到離屏 CanvasKit surface,不包含兄弟元素與祖先裁切/透明度;
|
|
722
|
+
文字、內部堆疊與子 canvas 沿用原有繪製,不修改 DOM,也不經 PNG、base64 或像素回讀。
|
|
723
|
+
快照以來源 border box、每 CSS pixel 一個像素繪製,下一次 draw 才更新,暫存影像隨用隨釋放。
|
|
724
|
+
目前不接受未連接、display:none、只有 inline box 的來源、iframe 或包含目標 canvas 的子樹;
|
|
725
|
+
一般 DOM 快照仍遵守來源的 CSS visibility。尺寸上限為單邊 8192、總計 16,777,216 像素,
|
|
726
|
+
跨來源圖片與受污染 canvas 的讀取限制會傳遞。
|
|
727
|
+
|
|
728
|
+
本地 QML 已接上 Flea 使用的 ShaderEffectSource:sourceItem、sourceRect、textureSize、
|
|
729
|
+
hideSource、live、scheduleUpdate 與 scheduledUpdateCompleted。live:false 保留快照,
|
|
730
|
+
更新完成後才發出通知;live:true 將 DOM 變更合併到下一個 animation frame,來源靜止時不持續截圖。
|
|
731
|
+
沒有 DOM 變動的任意 canvas/video 像素更新尚未自動追蹤。
|
|
732
|
+
多個材質共用來源時會計數引用;hideSource 只排除主畫面繪製,保留佈局與輸入,釋放時恢復來源。
|
|
733
|
+
被引用的 invisible QML 來源會保留佈局供截圖,來源本身的 opacity/位置變換不套進材質根節點;
|
|
734
|
+
但祖先 display:none 仍有限制。ShapePath.fillItem 可使用 ShaderEffectSource,支援 PathSvg、
|
|
735
|
+
PathRectangle 與獨立圓角;一般 Item fillItem、自訂 shader、遞迴材質、mipmap 與多重採樣仍未實作。
|
|
736
|
+
afterSynchronizing 在待處理快照完成後發出,但屬頁面事件迴圈,不代表原生 Wayland 顯示時間。
|
|
737
|
+
|
|
738
|
+
不需 Land 即可測試:`bun test test/qml-textures.test.js test/qml-canvas-dom.test.js`。
|
|
739
|
+
設定上面的 Flea/Omarchy/官方 binary 環境變數後,可跑
|
|
740
|
+
`bun test test/qml-flea-textures.test.js test/qml-flea-preview-backend.test.js`。
|
|
741
|
+
測試涵蓋原版 PreviewSwap 舊圖保留/釋放、HtmlClip 圓角、真正文字檔與 PNG 的 Quick Look 切換,
|
|
742
|
+
截圖留在 `/tmp/flea-real-preview-*.png`,測完會關閉 browser/backend。
|
|
743
|
+
測試:`bun test test/qml-canvas-dom.test.js`。
|
|
744
|
+
|
|
745
|
+
目前原版 Flea 已能啟動真正的主視窗、Theme/Commons/Ui、設定頁、鍵盤說明、
|
|
746
|
+
路徑輸入、網路分享表單,以及文字、CSV、Markdown、SVG/PNG 預覽。
|
|
747
|
+
Markdown 用原版 worker,圖片可測縮放與還原;Wayland 實測可用 Super-W 關窗。
|
|
748
|
+
所有應用程式測試都使用獨立 HOME/XDG,不寫個人設定,也沒有偽造後端回覆。
|
|
749
|
+
|
|
750
|
+
已解析 239 個 QML 檔案,235 個頂層 UI 元件中 231 個能編譯;這不是完整功能覆蓋。
|
|
751
|
+
剩餘三個編譯阻礙為 PDF 與 AnimatedImage 相關元件。
|
|
752
|
+
最初 73 項測試沒有 Flea 後端;後續已用 Omarchy 官方 0.3.12-1 aarch64 套件,
|
|
753
|
+
驗證官方 binary 直接呼叫我們的 `lib/qml/qs` wrapper,經標準 Wayland 顯示。
|
|
754
|
+
真實列檔、目錄新增通知、Ctrl-L/Enter 切換目錄及 Super-W 關閉已測過。
|
|
755
|
+
`DelegateModel.items.create()` 會在完成回呼前提供持久項目狀態,列表接手時
|
|
756
|
+
沿用既有項目,不重新建立。複製/搬移/刪除、掛載與預覽切換仍未完整驗證。
|
|
757
|
+
|
|
758
|
+
上方 `test/manual-flea-binary.js` 會呼叫官方 `flea --gui`,只對該程序把
|
|
759
|
+
暫時目錄放在 PATH 最前面,其中 `qs` 連結至 `lib/qml/qswayland`,
|
|
760
|
+
保留系統原本的 Quickshell;使用隔離 HOME/XDG
|
|
761
|
+
與範例檔案,關窗後清除。後端與 QML 請使用同一份套件。wrapper 支援
|
|
762
|
+
`-p/--path`、`-c/--config`,不支援的參數會明確失敗,不冒充原生 QS IPC。
|
|
763
|
+
列表與依賴 ShaderEffectSource 的預覽元件已能編譯,Quick Look 文字與 PNG 路徑已用官方後端驗證;
|
|
764
|
+
欄式檢視尚未宣稱完整覆蓋。無後端時仍是上游的 unavailable 狀態。
|
|
765
|
+
|
|
766
|
+
本機 QML 是有 Bun 權限的應用程式,使用專屬 renderer;HTTP QML 保持隔離。
|
|
767
|
+
匯入、singleton、alias、動態 Loader、模型/虛擬列表、鍵盤輸入、程序/檔案/worker
|
|
768
|
+
已接通所測路徑,但不是完整 Qt 相容層。多視窗、原生拖放、Quickshell IPC、媒體與
|
|
769
|
+
精確渲染同步等仍有限制,詳見上方各節。
|
|
770
|
+
|
|
771
|
+
### Termux udocker Debian 實驗
|
|
772
|
+
|
|
773
|
+
2026-10-23 已確認:官方 **Flea 0.3.12-1 aarch64** 可經 `qswayland` 在獨立
|
|
774
|
+
Debian 13(trixie)容器執行,畫面送到**容器外原本開著的 Land**。這次是透過
|
|
775
|
+
`jsgotty --client` 連入 Termux 原生 shell 後啟動,不是從開發用 Debian proot 再套一層。
|
|
776
|
+
|
|
777
|
+
容器名稱為 **`flea-qswayland`**,Termux 上的根目錄為
|
|
778
|
+
`~/.udocker/containers/flea-qswayland/ROOT`,ID 為
|
|
779
|
+
`82ef2c52-a491-4723-9604-855f22bd92d5`。先用
|
|
780
|
+
`udocker run -b "$TMPDIR:/tmp" debian` 建立,再以 `udocker rename` 命名。
|
|
781
|
+
|
|
782
|
+
除了 Flea 整包與 `/opt/buninu-browser`(不含 `.git`、`node_modules`),還複製了
|
|
783
|
+
Linux aarch64 glibc Bun 1.4.4 到 `/usr/local/bin/bun`,以及 Omarchy 的
|
|
784
|
+
`Commons`/`Ui` 到 `/usr/share/omarchy/shell/`。因此不是只複製兩份專案就足夠,
|
|
785
|
+
但沒有額外 apt/npm 安裝,也沒有安裝 Qt 或原生 Quickshell。
|
|
786
|
+
|
|
787
|
+
Flea 套件原本就有指向 Omarchy 模組的符號連結;另建立
|
|
788
|
+
`/usr/share/omarchy/qs → shell`,讓具名匯入能找到 `qs.Commons`/`qs.Ui`。
|
|
789
|
+
預設 PATH 中的 `/usr/local/bin/qs` 使用上方同一份 wrapper,先設定
|
|
790
|
+
`QML_IMPORT_PATH`,再直接執行 `qswayland`。
|
|
791
|
+
|
|
792
|
+
在 **Termux 原生端**重新進入:
|
|
793
|
+
|
|
794
|
+
```sh
|
|
795
|
+
udocker run -b "$TMPDIR:/tmp" flea-qswayland
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
在**容器內**啟動:
|
|
799
|
+
|
|
800
|
+
```sh
|
|
801
|
+
env XDG_RUNTIME_DIR=/tmp \
|
|
802
|
+
WAYLAND_DISPLAY=wayland-buninu \
|
|
803
|
+
QSG_RHI_BACKEND=opengl \
|
|
804
|
+
flea --gui /root
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
綁定 tmp 是為了共用 `/tmp/wayland-buninu` socket,Land 不搬入容器。
|
|
808
|
+
`QSG_RHI_BACKEND=opengl` 只是跳過 Flea 的原生 Vulkan 探測,不代表我們的前端
|
|
809
|
+
改用 GPU。官方 Flea 會從 PATH 找到 `qs`,再啟動真正的 `--backend`。
|
|
810
|
+
|
|
811
|
+
已從 Land 截圖確認容器內的 `/root/Documents`、`/root/hello.txt` 正常列出;
|
|
812
|
+
這只驗證啟動與基本列檔,不代表 Trash、掛載、預覽及所有外部工具整合都已可用。
|
|
813
|
+
容器內 `/root/FLEA-TEST.txt` 留有操作紀錄,共用 tmp 的
|
|
814
|
+
`/tmp/flea-udocker.log` 是測試 log。瀏覽器是複製的快照,更新專案後需重新同步。
|
|
815
|
+
|
|
816
|
+
本次解壓時 Android 拒絕建立 `/usr/bin/perl5.40.1` 硬連結,已把
|
|
817
|
+
`/usr/bin/perl` 複製成該檔案補齊;當次沒有回報其他解壓錯誤。
|
|
818
|
+
|
|
819
|
+
## Explicit backend entry points
|
|
820
|
+
|
|
821
|
+
The package launcher accepts Quickshell arguments independently of the backend:
|
|
822
|
+
|
|
823
|
+
```sh
|
|
824
|
+
bun index.js --quickshell-wayland -p /path/to/shell.qml
|
|
825
|
+
bun index.js --quickshell-headless -p /path/to/shell.qml -- --remote-debugging-port=9222
|
|
826
|
+
bun index.js --quickshell-casty -p /path/to/shell.qml
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
Each entry accepts `-p`/`--path`, `-c`/`--config`, and `-h`/`--help`.
|
|
830
|
+
Use `--` to pass subsequent arguments to the backend. For Casty, an additional
|
|
831
|
+
`--` forwards engine arguments, for example `-- -- --mobile`.
|
|
832
|
+
Standalone `lib/qml/qs` still launches Wayland directly without going through
|
|
833
|
+
`index.js`. These entries do not imply full native Quickshell compatibility.
|
|
834
|
+
|
|
835
|
+
套件入口可明確選擇 Wayland、headless 或 Casty,並使用相同的 QS 設定解析。
|
|
836
|
+
三個入口都接受 `-p`/`--path`、`-c`/`--config`、`-h`/`--help`。
|
|
837
|
+
用 `--` 分隔後端參數;Casty 再用一個 `--` 分隔瀏覽器引擎參數,
|
|
838
|
+
例如 `-- -- --mobile`。獨立的 `lib/qml/qs` 仍直接啟動 Wayland,
|
|
839
|
+
不經過 `index.js`。這些入口不代表已完整相容原生 Quickshell。
|
|
840
|
+
|
|
841
|
+
The same entries can run independently; `index.js` only routes arguments to them:
|
|
842
|
+
|
|
843
|
+
```sh
|
|
844
|
+
bun lib/qml/qswayland -p /path/to/shell.qml
|
|
845
|
+
bun lib/qml/qsheadless -p /path/to/shell.qml
|
|
846
|
+
bun lib/qml/qscasty -p /path/to/shell.qml
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
這三個檔案也能獨立執行;`index.js` 僅負責路由並原樣傳遞參數。
|
|
850
|
+
共同的 QS 解析與後端啟動邏輯位於 `lib/qml/launcher.js`。
|
|
851
|
+
原有 `lib/qml/qs` 保留原本的直接 Wayland 啟動方式。
|
|
852
|
+
|
|
853
|
+
### Text input and pointer fixes / 文字輸入與指標修正
|
|
854
|
+
|
|
855
|
+
文字輸入支援每 500 ms 切換顯示的遊標;失焦、隱藏、選取文字或銷毀時停止計時。
|
|
856
|
+
左右鍵會把選取折疊到對應端點,Shift 延伸選取,Home/End 與 Ctrl+A 共用選取狀態。
|
|
857
|
+
MouseArea 拒絕按下事件時,會把該次按下、釋放及點擊傳給下層項目。
|
|
858
|
+
ListView/GridView 換 model 時回到起點;更新同一個 model 則保留捲動位置。
|
|
859
|
+
這些都是通用 QML 行為,沒有依照 Flea 名稱或檔案路徑分支。
|
|
860
|
+
|
|
861
|
+
Tests / 測試:`test/qml-input-selection.test.js`、`test/qml-dynamic.test.js`、
|
|
862
|
+
`test/qml-views.test.js`、`test/qml-flea-preview-backend.test.js`。
|
|
863
|
+
|
|
864
|
+
Dynamic `createObject(parent)` ownership follows the explicit parent rather than
|
|
865
|
+
the Loader/binding currently executing. Destroying an unrelated Loader cannot
|
|
866
|
+
remove a surviving row's language icon. The official-backend navigation test
|
|
867
|
+
repeatedly enters an empty `~` and goes back, checking every language icon.
|
|
868
|
+
|
|
869
|
+
動態 `createObject(parent)` 依明確指定的父項目管理生命週期,不歸當時執行中的
|
|
870
|
+
其他 Loader 或 binding 所有。清除其他 Loader 不會再連帶刪掉仍存活檔案列的圖示。
|
|
871
|
+
`test/qml-flea-navigation-backend.test.js` 使用官方後端反覆進入空的 `~` 再返回,
|
|
872
|
+
確認各個語言圖示仍有內容。示範測試的 `HOME` 是隔離目錄;「NOTHING HERE YET」
|
|
873
|
+
表示該目錄為空,不表示 `~` 展開失敗。
|
|
874
|
+
|
|
875
|
+
### Markdown preview layout / Markdown 預覽排版
|
|
876
|
+
|
|
877
|
+
ListView uses sparse measured sizes to place unequal-height blocks without
|
|
878
|
+
overlap, including later height changes, scrolling and viewport resizing.
|
|
879
|
+
Formatting whitespace between markup blocks does not add phantom text lines.
|
|
880
|
+
PlainText retains explicit trailing newlines. No Flea-specific renderer is used.
|
|
881
|
+
|
|
882
|
+
ListView 依各區塊實際高度排列,並追蹤後續高度變化;捲動與視窗改變大小時仍維持
|
|
883
|
+
有限範圍的虛擬列表。未見過的區塊使用估計高度,不會建立整份文件。標籤區塊間的
|
|
884
|
+
格式換行不再增加虛構文字行;PlainText 的明確換行則保留。這是通用 QML 修正。
|
|
885
|
+
|
|
886
|
+
Tests / 測試:`test/qml-views.test.js`、`test/qml-layout-text.test.js`、
|
|
887
|
+
`test/qml-flea-markdown-backend.test.js`。
|
|
888
|
+
|
|
889
|
+
Markdown pre-reading also uses `StdioCollector.data`: the collector exposes the
|
|
890
|
+
original bytes as an ArrayBuffer separately from decoded text, and signal
|
|
891
|
+
handlers run with their declaring QML object as `this`. Byte concatenation is
|
|
892
|
+
lazy and only occurs when `data` is read.
|
|
893
|
+
|
|
894
|
+
Markdown 預讀使用的 `StdioCollector.data` 已提供原始位元組 ArrayBuffer,與解碼後
|
|
895
|
+
的文字分開;讀取 `data` 時才合併位元組。訊號處理函式的 `this` 指向宣告它的
|
|
896
|
+
QML 物件,供 `this.text`/`this.data.byteLength` 等標準用法使用。
|
|
897
|
+
|
|
898
|
+
MarkdownText collapses paragraph soft breaks as HTML whitespace while preserving
|
|
899
|
+
explicit hard breaks and fenced code lines. Proportional text line height uses
|
|
900
|
+
the same measured font line box for CSS painting and QML geometry, including
|
|
901
|
+
fallback glyph metrics, so CJK code lines do not crowd into a taller item box.
|
|
902
|
+
|
|
903
|
+
MarkdownText 將段落的軟換行視為 HTML 空白,保留明確換行與程式碼區塊的逐行內容。
|
|
904
|
+
比例行高在 CSS 繪製與 QML 幾何計算使用相同字型行框,包含替補字型的度量,
|
|
905
|
+
避免中文程式碼擠在較高區塊的上方。
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
## Media playback / 媒體播放
|
|
909
|
+
|
|
910
|
+
Local QML supports a subset of QtMultimedia: MediaPlayer, AudioOutput and
|
|
911
|
+
VideoOutput reuse the browser's existing HTML media decoder, clock, seeking,
|
|
912
|
+
video presentation and PulseAudio output. No native Qt plugin or new decoder
|
|
913
|
+
is loaded. Source loading, autoPlay, play/pause/stop, millisecond position and
|
|
914
|
+
duration, playback/media status, looping, volume/mute, and fit/crop/stretch
|
|
915
|
+
video output are available. VideoOutput exposes sourceRect/contentRect.
|
|
916
|
+
Changing the source or destroying a player releases its output and decoders.
|
|
917
|
+
Audio still requires the browser's usual jspulse/PulseAudio server on
|
|
918
|
+
127.0.0.1:4713 for audible playback.
|
|
919
|
+
|
|
920
|
+
Quickshell.Wayland IdleInhibitor is accepted with supported=false. Enabling it
|
|
921
|
+
prints a warning; it neither prevents sleep nor blocks playback. Playback rate,
|
|
922
|
+
track selection, subtitles, camera capture, video rotation/mirroring and native
|
|
923
|
+
MPRIS integration are not implemented by this adapter. Flea's own external
|
|
924
|
+
MPRIS helper remains subject to its ordinary host prerequisites.
|
|
925
|
+
|
|
926
|
+
The only renderer integration is in removable qml handle blocks: a capability
|
|
927
|
+
adapter to existing media operations and optional gain on the already converted
|
|
928
|
+
PCM output chunk. Video is not re-encoded or captured into an additional canvas.
|
|
929
|
+
See Qt's [MediaPlayer](https://doc.qt.io/qt-6/qml-qtmultimedia-mediaplayer.html)
|
|
930
|
+
and [VideoOutput](https://doc.qt.io/qt-6/qml-qtmultimedia-videooutput.html) APIs.
|
|
931
|
+
|
|
932
|
+
本地 QML 的 MediaPlayer、AudioOutput、VideoOutput 沿用瀏覽器現有的
|
|
933
|
+
HTML 媒體解碼器、時鐘、跳轉、影片繪製與 PulseAudio 輸出,不新增 Qt plugin
|
|
934
|
+
或另一套解碼器。支援來源載入、自動播放、播放/暫停/停止、以毫秒表示的位置與長度、
|
|
935
|
+
播放狀態、循環、音量/靜音,以及影片等比例縮放、裁切與拉伸。
|
|
936
|
+
VideoOutput 提供 sourceRect/contentRect;換來源或銷毀播放器時會釋放輸出與解碼器。
|
|
937
|
+
實際發聲仍需瀏覽器原本使用的 127.0.0.1:4713 jspulse/PulseAudio 服務。
|
|
938
|
+
|
|
939
|
+
IdleInhibitor 可載入但 supported=false;啟用時只提示,不會阻止休眠,也不阻止播放。
|
|
940
|
+
播放速度、音軌選擇、字幕、攝影機、影片旋轉/鏡像及原生 MPRIS 整合尚未實作;
|
|
941
|
+
Flea 自己的外部 MPRIS helper 仍需其原本的主機條件。
|
|
942
|
+
Renderer 接入仍全部位於可移除的 qml handle 區塊;影片不重編碼、不另建 Canvas,
|
|
943
|
+
音量僅處理既有 PCM 輸出區塊。
|
|
944
|
+
|
|
945
|
+
Validation: bun test test/qml-media.test.js checks real MP4/MP3 metadata and
|
|
946
|
+
seeking, paused video pixels, real decoded MP3 PCM through an in-memory audio
|
|
947
|
+
device, mute and output closure. With BUNINU_FLEA_ROOT and BUNINU_OMARCHY_ROOT,
|
|
948
|
+
test/qml-flea-media.test.js also loads Flea's unchanged PreviewMedia.qml.
|
|
949
|
+
測試包含真實 MP4/MP3、跳轉、影片截圖與記憶體音訊端的 PCM、靜音、關閉;
|
|
950
|
+
設定 Flea/Omarchy 來源路徑後,也測試未修改的 PreviewMedia.qml。
|
|
951
|
+
|
|
952
|
+
### Optional placeholder video thumbnails
|
|
953
|
+
|
|
954
|
+
The isolated Flea experiment can use `test/fixtures/flea-thumbnail-stub/`:
|
|
955
|
+
copy `flea-thumbnail-stub` to `/usr/local/bin/` (executable) and
|
|
956
|
+
`flea-placeholder.thumbnailer` to `/usr/share/thumbnailers/`, then restart Flea.
|
|
957
|
+
The 3-line shell stub writes the same opaque 1×1 PNG for every registered video
|
|
958
|
+
format; it does not decode the video or provide metadata. The registration file
|
|
959
|
+
is 4 lines. Flea 0.3.12's actual backend accepted it and published a stamped cache
|
|
960
|
+
PNG (`thumbed.file` nonempty), using the existing experimental bwrap bypass.
|
|
961
|
+
This avoids the missing-thumbnail message without changing Flea's QML.
|
|
962
|
+
Remove the registration to disable it; already generated placeholder thumbnails
|
|
963
|
+
remain in Flea's thumbnail cache until invalidated or removed.
|
|
964
|
+
|
|
965
|
+
隔離 Flea 實驗可使用 `test/fixtures/flea-thumbnail-stub/`:將可執行的
|
|
966
|
+
`flea-thumbnail-stub` 放入 `/usr/local/bin/`,註冊檔放入
|
|
967
|
+
`/usr/share/thumbnailers/`,再重開 Flea。shell stub 只有 3 行,註冊檔
|
|
968
|
+
4 行;所有註冊的影片都使用同一張不透明 1×1 PNG,不解碼影片也不提供
|
|
969
|
+
媒體資訊。官方 0.3.12 後端已實測接受並寫入縮圖快取,沿用實驗容器的
|
|
970
|
+
bwrap 繞過路徑,無須修改 Flea QML。刪除註冊檔可停用,但既有佔位縮圖
|
|
971
|
+
仍保留在快取,直到失效或被移除。
|