Files
Nebula-OS/shells/desktop/native/README.md
T
andrew 2dadead399 Add native Wayland shell host scaffolding
Introduce a Linux-only C++20 `nebula-shell` host built with CMake, GTK4, gtk4-layer-shell, and WebKitGTK 6.0. Add a shared `Surface` abstraction and concrete Desktop/TopBar/Launcher surfaces with layer placement, sizing, transparency, and per-surface `?surface=` URL loading.

Add `ShellApplication` startup flow that validates `NEBULA_SHELL_DEV_URL`, checks layer-shell support, creates/presents desktop and top bar, and keeps launcher created but hidden for future bridge-driven toggling. Update the native README to document architecture, development setup, dependencies, and current milestone scope.
2026-08-26 15:44:44 +12:00

3.7 KiB

Nebula Desktop native host

nebula-shell hosts the React-based Nebula Desktop chrome as real Wayland Layer Shell surfaces.

It is a C++ process that creates several GTK4 windows, each backed by WebKitGTK 6.0 and placed with gtk4-layer-shell. It does not composite application windows. Those remain ordinary Wayland / XWayland clients of the compositor.

Stack:

  • C++20
  • GTK4
  • gtk4-layer-shell
  • WebKitGTK 6.0
  • CMake
  • Wayland

This host is Linux-only. It will not compile on Windows.

Purpose

Nebula Desktop's React UI is shell chrome only: wallpaper/desktop, top bar, and launcher. nebula-shell maps each of those to a Wayland layer surface so they sit in the compositor like a real desktop environment, not like a browser window.

Normal applications and games never render inside WebKit.

Architecture

Nebula Shell
├── DesktopSurface
│   ├── WebKitGTK
│   ├── ?surface=desktop
│   └── BACKGROUND
│
├── TopBarSurface
│   ├── WebKitGTK
│   ├── ?surface=topbar
│   └── TOP
│
└── LauncherSurface
    ├── WebKitGTK
    ├── ?surface=launcher
    └── OVERLAY
Surface Query Layer Shell layer Placement
Desktop ?surface=desktop BACKGROUND Anchored to all monitor edges
Top Bar ?surface=topbar TOP Anchored top/left/right, 40px (matches the React top bar), exclusive zone enabled
Launcher ?surface=launcher OVERLAY Created at startup, hidden/unmapped until later toggle work
OVERLAY
    Nebula Launcher   ← created, currently unmapped
    notifications
    OSDs

TOP
    Nebula Top Bar   ← exclusive zone; apps do not go under it

NORMAL APPLICATION WINDOWS
    Firefox, Steam, Blender, games, terminals, …

BACKGROUND
    Nebula Desktop
    wallpaper

React draws shell chrome only. Applications and games render through the compositor, not through WebKit:

App
 ↓
Wayland / XWayland
 ↓
Compositor
 ↓
GPU

Development

The host must not hardcode a Vite host or port. It reads a base origin from the environment and appends the surface query parameter.

Start the React UI (the port is an example, not part of the native architecture):

cd shells/desktop/ui
npm run dev -- --host 127.0.0.1 --port 5174 --strictPort

Point the shell at that origin:

export NEBULA_SHELL_DEV_URL=http://127.0.0.1:5174

That loads:

{NEBULA_SHELL_DEV_URL}/?surface=desktop
{NEBULA_SHELL_DEV_URL}/?surface=topbar
{NEBULA_SHELL_DEV_URL}/?surface=launcher

Build:

cd shells/desktop/native

cmake -S . -B build
cmake --build build -j$(nproc)

Run inside a Wayland compositor such as Sway:

./build/nebula-shell

On startup the desktop and top bar are presented. The launcher is created but left hidden.

A combined browser preview (/?surface=preview, also the default) is for Windows UI work only. The native host loads the three surfaces separately.

Linux packages

Build dependencies (install on the Ubuntu machine, not from this tree):

libgtk-4-dev
libgtk4-layer-shell-dev
libwebkitgtk-6.0-dev
pkg-config
cmake
build-essential

Production

Production loading from bundled shells/desktop/ui/dist files is not implemented yet. This milestone is development-URL loading only.

Shell bridge

Not implemented in this milestone. Each WebKit view will later talk to the host through a JavaScript bridge (shellBridge in the React UI) so the top bar can map and unmap LauncherSurface.

Current development compositor

Sway is the temporary compositor. See compositor/sway/nebula-sway.conf.