Files
NotAlexNoyleandClaude Opus 5.5 f50e49c128 T-544: the card holds sticky sidebars and fixed bars still between frames of a pan
The owner, watching finger pans: "the center column is scrolling/panning smoothly but the sidebars
are not". Between frames the card moved the whole frame it holds, desktop Wikipedia's sticky sidebars
with it, and each new frame put them back. Engine 0068 returns each frame's fixed and stuck rects
with its poll; the daemon writes them and the view row into the 192 bytes before the segment
trailer (JihadStuckBlock, tagged with the frame's number; JIHAD_GPU_NO_HOLD=1 off); the adapter draws
them where the frame drew them and covers their moved copy in the page's colour beside them.
Four mid-drag screenshots each way: sidebars at +0 px in all four with it (the column moved up to
150 px), displaced 11-12 px in two of four without; no ghost; frame rate unchanged.
R3's pan criterion is re-opened against the corrected test (the owner's choice): with the card
moving desktop Wikipedia pans at ~7 fps. The card-redraw throttle prototype showed no gain and is not
kept. UXP_PIN and SRCREV at 078a0942.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KP7JxhNqPrvYp27QDy8hP8
2026-10-26 07:02:14 -04:00
..

render/browserserver — engine-agnostic render daemon + IPC

Derived from the isis-project BrowserServer / BrowserAdapter / AdapterBase (Apache-2.0). This directory holds the parts of the render daemon that are independent of the rendering engine and are kept unchanged across the QtWebKit → Goanna swap.

Self-contained naming: the daemon's YAP server name is set from JIHAD_BS_NAME (Main.cpp), so it serves /tmp/yapserver.jihad-browser instead of the stock browser socket — letting Jihad coexist with the stock browser rather than replace it. The YAP command/message interface is byte-identical; only the socket name differs. The matching adapter is built as BrowserAdapterJihad.so (MIME application/x-jihad-browser). See ../../packaging/README.md and auto-memory jihad-self-contained-arch.md.

Runtime state (T-057, cavekit-device-build R8): the daemon derives ONE variant-scoped state directory from JIHAD_BS_NAME in ../goanna/JihadRuntimePaths.h — /var/palm/jihad/{enyo,mochi,mojo}/ on the device (root-owned 0755), per context/plans/plan-variant-identity.md. The engine profile/cache, the frame dump and the self-drive inject channel all live there; nothing is written to /media/internal (the user's USB mass-storage volume). Off-device (no writable /var/palm) it falls back to $HOME/.jihad/<variant>/, then /tmp/jihad-<uid>/<variant>/. Env knobs: JIHAD_STATE_DIR overrides the directory; JIHAD_INJECT=1 turns the DEBUG self-drive channel ON (off by default — see JihadBrowserServer.cpp); JIHAD_DUMP=1 writes <state>/frame.ppm; JIHAD_PROFILE_DIR overrides the profile.

Termination (2026-08-04): Main.cpp handles SIGTERM/SIGINT/SIGHUP — the handler only sets a flag, and the 16 ms tick quits the GLib loop, because g_main_loop_quit is not async-signal-safe. This is not hygiene. stop <job> sends SIGTERM, and the engine's state is written by DEFERRED savers (the add-on database, prefs) that only flush during XPCOM shutdown; with the default action, main() never returned, XRE_TermEmbedding never ran, and those changes were lost — an extension disabled from about:addons came back enabled. main() also SCOPES the server so every page (and nsIWebBrowser) is destroyed before the runtime; the other order crashes in engine teardown. Two never-executed teardown paths were broken when they first ran: YapServerPriv::deadlockDetector is uninitialized and run()'s default never creates it, yet ~YapServer deletes it anyway; and ~YapServerDeadlockPriv quit a null loop and joined thread 0. Anything you add on the shutdown path is, until proven otherwise, untested code.

The upstream sources are cloned for reference at ../../../ref-BrowserServer, ../../../ref-BrowserAdapter, ../../../ref-AdapterBase. During Phase 1 the reusable files are imported here (keeping their Apache-2.0 headers); the QtWebKit-specific files are replaced by the Goanna backend in ../goanna.

Keep (engine-agnostic)

  • YAP server / IPC: BrowserServerBase.{h,cpp} (autogenerated interface), IpcBuffer, BrowserSyncReplyPipe, the YAP dispatch. Do not hand-edit — regenerate. The generator and the authoritative .defs are both IN this tree at CodeGen/ (see CodeGen/README.md for the build + regenerate loop); the upstream copies in ../../../ref-BrowserServer/CodeGen are STALE and must not be used (measured 2026-08-10: that .defs has no 0x1600 and reverts KeyDown/KeyUp to two uint16_t; that generator emits every async command as = 0;). Command 0x1600 asyncCmdSetExtraBuffer was added on 2026-08-10 to announce a third shared framebuffer, because connect/thaw carry exactly two keys and their shapes are frozen. It is declared non-pure-virtual with an empty default body so a server without a third buffer still compiles; since 2026-08-15 the vendored generator emits that body from the optional flag in the .defs, so a regeneration needs no hand edit. build/webos-oe/check-yap-contract.sh fails the build on any of it. Rationale and measurements: docs/IPC-CONTRACT.md.
  • Daemon & lifecycle: Main.cpp, BrowserServer.{cpp,h} (minus QtWebKit bits), BrowserServerBase, BrowserPageManager, CpuAffinity, PluginDirWatcher, Settings.
  • Shared framebuffer plumbing: the shmem attach/return/double-buffer logic and BrowserOffscreenInfo pixel-format contract (the interface; the Qt implementation BrowserOffscreenQt is replaced).
  • LunaService surface: palm://com.palm.browserServer/{clearCache,clearCookies}.
  • Backup manager, SSL/cert glue (BackupManager, SSLSupport, SSLValidationInfo) — re-pointed at Goanna's cert APIs.
  • JSON utils (JsonUtils, pbnjson usage).

Replace (QtWebKit-specific)

  • BrowserPage.{cpp,h} — QGraphicsView/QGraphicsWebView/WebOSWebPage internals → render/goanna/BrowserPageGoanna (nsIWebBrowser + offscreen widget). The public method surface of BrowserPage is preserved so the YAP command dispatch in BrowserServerBase calls it unchanged.
  • BrowserOffscreenQt.{cpp,h} — Qt pixmap/QImage surface → a Goanna surface that paints into the same shmem buffer (BrowserOffscreenInfo).
  • WebKitEventListener.{cpp,h} — QtWebKit signal handlers → Goanna nsIWebProgressListener/chrome listeners in the Goanna backend.
  • Qt build deps (qbsinterface, weboswebpage.h from webkit-supplemental).

Boundary

BrowserServerBase dispatches each YAP command to a BrowserPage*. We keep that vtable identical and provide it from the Goanna backend. That single boundary is what makes "swap the core, keep the IPC" mechanically possible.