The full path

Figure 01. Display and inputapp to A10

The bridge app

For the X11 and Wayland desktops, one app carries the whole thing: Xios.app, which shows on the Home Screen as X11. It owns a CAMetalLayer and the UIKit input surface, and it draws none of the desktop's own content. At startup a display server creates an output IOSurface and passes its mach port to the app. The app adopts that surface, wraps it as a Metal texture, and draws it every frame. When a server redraws the desktop, the app shows the new contents without copying a single pixel.

Because the app holds the screen and the input, the servers never touch UIKit. That keeps them close to their upstream form, which is what makes cross-compiling them tractable.

What the app does draw is its own chrome: a thin status overlay you pull down from the top edge, and a control panel on a three-finger tap that starts and stops desktops, resizes a running one, picks which apps get Home Screen icons, and lists the display slots you have open. It is also the process that owns hardware iOS will not hand to a daemon, so camera frames and VoiceOver state reach the desktop through it. Native mode is the one path that bypasses this app: each Linux app there gets its own per-window host bundle.

Three ways to drive the same output

Every compositor produces the same thing: an output IOSurface the app can present. From the app's side they are interchangeable, which is what lets you switch desktops without the app knowing much beyond which one it pinned.

iosc
A clean-room libwayland-server compositor. It composites clients on the GPU and serves around thirty protocols, from xdg-shell and subsurfaces up through touch, tablet, layer-shell, screencopy, the text-input-v3 keyboard bridge, and the private iosc_iosurface buffer protocol.
Mutter
GNOME Shell's compositor, given a native iOS backend (MetaBackendIOS) so it renders into the output IOSurface itself rather than nesting inside iosc.
KWin
Plasma's compositor, which does nest: iosc owns the output surface, and kwin_wayland runs inside it as a Qt/ANGLE client that composites Plasma's windows into its own IOSurface first.

X11 apps reach the same output through Xwayland, which runs against iosc as an ordinary client with glamor rendering X pixmaps through ANGLE into IOSurfaces. There is no separate X server any more: the software, Xvfb-derived one was retired on 2026-07-29, leaving Xvfb and Xvnc as headless bring-up tools only.

A Wayland frame

  1. A GTK4 app renders with GLES through ANGLE into its own IOSurface.
  2. It hands that surface to iosc over a mach port, as an IOSurface wl_buffer.
  3. iosc binds it as a GL texture and composites it with every other window into the output IOSurface, on the GPU.
  4. Xios.app presents that output IOSurface as a Metal texture on the screen.

No CPU copy happens between step one and step four. A window's pixels are drawn once by the GPU and scanned out by the same GPU. Apps that still paint into wl_shm buffers, and the whole classic X11 path, do pay a CPU upload; under Plasma there is one extra GPU pass, because KWin composites before iosc does.

Input, in reverse

A tap or keystroke enters UIKit inside the app and crosses a small socket as a fixed-size record. It reaches iosc or Mutter and turns into wl_pointer, wl_keyboard, wl_touch or tablet events for the focused window.

The wire carries more than taps: multitouch slots, Apple Pencil pressure and tilt, scroll with a finger-versus-wheel source, and raw HID from a physical keyboard, mouse or trackpad, including chords, key repeat, five mouse buttons and Command mapped to Super. It is not one-directional either. The same socket carries records back up to the app: text-input traits that tell iOS which keyboard to raise, haptic requests, and rotation and output geometry.

Sessions, slots and the supervisor

Nothing starts a desktop directly. ioscd is a root daemon that owns session lifecycle: it launches clients that would otherwise inherit a sandboxed identity from a Home Screen tap, foregrounds Xios.app, restarts a compositor that died, and decides who is allowed to switch sessions at all. That last part is a real trust boundary, added after stray requests were tearing down healthy desktops in a loop: root and the picker app may switch, everyone else can only ask for a session to exist.

xios-session is the command underneath, with presets for iosc, Mutter, GNOME Shell, Plasma Desktop, Plasma Nano and Plasma Mobile. Pass it a slot name and you get a second desktop with its own Wayland socket, config and status file, which the app lists so you can pin one and switch between them.

Hardware and POSIX bridges

Drawing pixels and routing input is only half the job. A desktop also expects a battery, a brightness slider, sound, Bluetooth, orientation, and a logged-in user. None of that exists in the Linux sense on iOS, so a set of small daemons translate each one, reading the real iOS API and republishing it as the D-Bus service, Wayland protocol, or sysfs file the desktop is looking for.

System integration walks through how each one works, from audio to Bluetooth.