Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Module core/app/interaction/context-menu-ownership

    Native context-menu ownership — the secondary click belongs to the viewer on every surface the viewer owns, not just on the canvas.

    Right-drag orbits the camera, so both controls implementations already preventDefault the contextmenu event on the canvas they listen to (luxar-orbit-controls.ts, luxar-fly-controls/listeners.ts), and canvas-actions.ts repeats it. In Chromium that is enough: every scene overlay floating above the canvas is pointer-events: none, so the hit test walks past the overlay and the event target IS the canvas.

    WebKit resolves the context-menu target geometrically instead, so inside the WKWebView of an exported --native macos app the target is whichever overlay happens to sit under the cursor — a turntable's matte <canvas>, its <video>, a logo <img>. None of those is the canvas and none of their ancestors carried a handler, so the native "Copy Image / Share Image…" sheet opened over the scene the moment a right-drag began, and the camera never moved. Reported against the ESM kiosk export, 2026-09-09.

    Rather than chase each overlay, one delegated listener on the viewer container covers everything the viewer mounts — present and future, pointer-events or not. It is scoped two ways so it cannot eat a menu that is not ours to eat:

    • Ownership. Only a target that is the canvas, or that sits inside an element carrying a luxar- class, is suppressed. Universal ancestors (the container, body and document element) do not establish ownership: the container defaults to document.body, which an embedder may share with their own UI (see utils/viewer-container).
    • Text entry. A typing surface keeps its native menu, which is the only way to paste — while range, checkbox, radio and select controls remain viewer controls whose menu should be suppressed.
    • Interactive overlay actions. A live selection keeps Copy, and a link keeps its native link actions. The overlay's pointer events already prevent a right-drag from reaching the camera controls.

    Capture phase, so an inner handler that calls stopPropagation (the dimension sliders' play-button menu does) cannot leave the native menu behind it.

    installContextMenuOwnership