Skip to content

Lucifer: per-app namespaces (wm/wm crash), app cursors, on-screen keyboard types where you clicked - #1122

Draft
pdfinn wants to merge 3 commits into
masterfrom
fix/lucifer-app-ns
Draft

pdfinn wants to merge 3 commits into
masterfrom
fix/lucifer-app-ns

Conversation

@pdfinn

@pdfinn pdfinn commented Nov 8, 2026

Copy link
Copy Markdown
Member

Rebuilds three fixes made on 2026-11-05 and lost with the SSD before they were pushed (old commits cdaab5fc, 365f49af in part, and 83fee21f). They were re-applied by hand on current master.

What was broken

  1. Opening wm (wm/wm) inside Lucifer broke every app opened after it. wm/wm puts its own window server over /chan/wmctl. Lucifer started Activity 0's apps in Lucifer's own namespace, so that bind covered Lucifer's /chan/wmctl for everything opened later, and each of those apps became wm/wm's client instead of Lucifer's. The effects:

    • osk got a black tab;
    • a shell in wm took no typing;
    • About and Charon tabs were blank.

    When one of those clients left without joining, wm/wm sent on its nil stop channel and died with [Wm] Broken: "dereference of nil".

  2. App cursors never changed under Lucifer. wm/wm's cross, move box and gunsight are cursor requests to its window server. Lucifer answered OK and dropped them.

  3. The on-screen keyboard typed into the wrong zone when used with a mouse. Lucifer sends keys to whichever zone the mouse is over. With the pointer on osk's strip, the zone that counted was the one the mouse last crossed on its way down, often the app between the chat and the keys, not the one you clicked in.

What changed

  • appl/cmd/lucifer.b launchappns: FORKNS for every app, Activity 0's included.
  • appl/wm/wm.b: wm/wm skips the stop for a client that never joined, the same nil check Lucifer's own handler has.
  • appl/cmd/lucifer.b: a cursor request is written to /dev/cursor in wmlib's format, and a malformed request is refused.
  • appl/cmd/lucifer.b: while the pointer is in osk's strip, keys go to the zone of the last press outside it. Everywhere else the mouse decides, as before.

Under bare wm/wm, osk already typed into the window last clicked (wm/wm is click-to-focus). The new osk_test steps pin that behaviour; they don't fix anything there.

Tests

New:

  • tests/host/lucifer_wmapp_test.sh opens wm, then osk, then About.
    • On master: FAIL: osk: 1 processes broken, FAIL: about: 1 processes broken, FAIL: [Wm] Broken: "dereference of nil".
    • On this branch: ALL PASS.
  • tests/host/lucifer_cursor_test.sh uses the SDL cursor shim.
    • On master: FAIL: cross: cursor '', want the cross and FAIL: a malformed cursor request was not refused.
    • On this branch: ALL PASS.

Extended:

  • osk_lucifer_test.sh types with the mouse in three cases:

    • after a click in the chat, then over a shell in the zone;
    • after a click in that shell, then over the chat;
    • into wm/wm's own shell in the zone.

    Without the routing change all three fail (FAIL: with the mouse to the chat: the conversation 4 then 4, the shell 'sh: hi: ...', and likewise the other two). With it they pass.

  • osk_test.sh (under wm/wm): a wm/editor clicked in and then the shell, each typed into by finger and by mouse.

Final run on this branch, Linux arm64, SDL dummy driver, every result ALL PASS:
lucifer_wmapp_test, lucifer_cursor_test, osk_lucifer_test, osk_test, wm_test, wm_ghost_test, wm_cursor_test, lucifer_app_test. tools/check-mkfile-deps.py reports OK.

Decision needed before merge: Matrix's /mnt/matrix

With a namespace per app, whatever an Activity 0 app mounts stays in its own namespace. I checked this by booting Lucifer, opening wm/matrix as an app, and listing /mnt/matrix from the boot shell:

  • on master the listing has 5 entries;
  • on this branch it is empty.

docs/matrix-architecture.md says Veltro controls a GUI-mode Matrix through /mnt/matrix, so this branch may stop the agent's matrix tool from reaching a Matrix opened in Lucifer. wm/wm's /mnt/wm export is affected the same way. I haven't checked what the agent's tool namespace actually sees.

There are two options, and this PR does not choose between them:

  • Keep this PR as it is. Matrix then needs another way to reach Lucifer's namespace, such as posting to #s.
  • Leave Activity 0 sharing as it was. wm/wm would instead fork its own namespace before it serves /chan/wmctl: a window manager running as a client keeps its binds to itself.

🤖 Generated with Claude Code

https://claude.ai/code/session_0195u6z8KPZLwsNLmii58Rqa

pdfinn and others added 3 commits November 8, 2026 18:52
… that never joined

wm/wm, opened as an app in Lucifer (the context browser lists
/dis/wm), puts a window server of its own over /chan/wmctl.  Lucifer
started Activity 0's apps in its own namespace, so that bind covered
Lucifer's /chan/wmctl for every app opened after it: each became
wm/wm's client, not Lucifer's -- osk's tab was black, a shell in wm
took no typing, About and Charon tabs were blank.  When such a client
left without joining, wm/wm sent on its nil stop channel and broke
("[Wm] Broken: dereference of nil", appl/wm/wm.b).

launchappns now forks the namespace for every app, Activity 0's
included, and wm/wm skips the stop for a client with none, as
Lucifer's own handler already does.

tests/host/lucifer_wmapp_test.sh opens wm, then osk, then About:
without the fix osk and About each leave a broken process and About
never runs; with it, all pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z8KPZLwsNLmii58Rqa
wm/wm asks its window server for New's cross, the box for a move and
Delete's gunsight with a "cursor" request.  Bare, wmlib writes
/dev/cursor itself; in Lucifer the request went to Lucifer, which
answered OK and dropped it, so the cursor never changed (the actions
worked).  Any app setting a cursor was affected.

Lucifer now writes the request to /dev/cursor in wmlib's form
(header low byte first, as bplong), and refuses a malformed one.

tests/host/lucifer_cursor_test.sh sends rio's cross, the arrow and a
bad request, checking each SDL cursor call through the shim
wm_cursor_test.sh uses: without the change no cursor call is made and
the bad request is accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z8KPZLwsNLmii58Rqa
In Lucifer the keyboard follows the mouse: keys go to the
presentation zone's app while the pointer is over it, else to the
chat.  Typing on wm/osk with a mouse, the pointer is on the keyboard's
strip, and the last place it was before that is wherever it crossed on
the way down -- often the app between the chat and the strip.  A
click in the chat, then keys tapped with the mouse, typed into the
app; a click in a shell in the zone, then over the chat, typed into
the chat.

While the pointer is in the strip, the keys now go to the zone of the
last press outside it.  Elsewhere the mouse still decides, so the
machine's keyboard behaves as before; with touch the last tap already
decided.

tests/osk/lucifer.sh types with the mouse after a click in the chat
(over a shell in the zone), after a click in that shell (over the
chat), and into wm/wm's shell in the zone: without the change all
three go astray.  tests/osk/drive.sh pins the same under wm/wm, which
already sent keys to the window clicked in: a wm/editor and the shell,
by finger and by the mouse moved over the other window first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195u6z8KPZLwsNLmii58Rqa
@pdfinn

pdfinn commented Nov 8, 2026

Copy link
Copy Markdown
Member Author

Held until after the 2026-11-08 release, by the user's decision. Open design question before merge: per-app namespaces (as here, with Matrix publishing /mnt/matrix another way) vs Activity 0 sharing with wm/wm forking its own namespace before serving /chan/wmctl.

@pdfinn
pdfinn marked this pull request as draft November 8, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant