surfer
A neat, minimal, opinionated windowing library for Nim.
Summary
| Latest Version | 0.2.5 |
|---|---|
| License | BSD-3-Clause |
| CI Status | Failing |
| Downloads | 0 |
| Last Indexed | 2026-09-04 07:26 |
Tags
Authors
- xTrayambak
Installation
nimble install surfer
choosenim install surfer
git clone https://github.com/nim-windowing/surfer
OS Compatibility
| Platform | Linux | macOS | Windows | FreeBSD | OpenBSD | NetBSD | Android | iOS | WASM | Embedded |
|---|---|---|---|---|---|---|---|---|---|---|
| surfer | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
Dependencies
| Package | Version | Optional |
|---|---|---|
| nim >= | 2.2.0 | No |
| nayland >= | 0.3.0 | No |
| shakar >= | 0.1.3 | No |
| xkb >= | 1.4.1 | No |
| vmath >= | 2.0.1 | No |
| chroma >= | 1.0.0 | No |
| gh:nim-windowing/linux_input >= | 0.1.0 | No |
Source
| Repository | https://github.com/nim-windowing/surfer |
|---|---|
| Homepage | https://github.com/nim-windowing/surfer |
| Registry Source | nimble_official |
README
surfer
Surfer is a high-level, opinionated windowing library written in Nim.
It has one simple goal: Do one thing (windowing), and do it better than any other Nim windowing library.
It does not try to be your networking stack, your rendering stack or anything else. It handles windowing, input and buffer management. That's it.
Currently, it only supports a Wayland backend through the nayland library. On its Wayland backend, Surfer can be used to write desktop shells, launchers, status bars, notification daemons and other layer-based programs using the zwlr-layer-shell-unstable-v1 protocol.
installation
Surfer can be installed via Neo, as well as Nimble.
$ neo add gh:nim-windowing/surfer
basic example
Surfer is designed to be an easy-to-use library, with minimal gotchas like global states that come to vex you later on. - Basic CPU rendering - Layer Shell example - Idle Inhibit example - EGL + OpenGL ES example
Here's a tiny program that uses CPU rendering. Surfer tries to abstract away buffer allocation to the best of its abilities, due to its origin as the windowing backend for a software-rendered (now GPU accelerated) terminal emulator, nitty.
import pkg/[vmath, shakar, surfer, chroma, pixie]
proc main() {.inline.} =
let app = newApp("Surfer Example", appId = "xyz.xtrayambak.surfer")
app.initialize()
app.createWindow(ivec2(680, 480), Renderer.Software)
echo "Has keyboard: " & $hasKeyboard(app)
echo "Has cursor: " & $hasCursor(app)
# Use ControlFlow.Wait for simple GUI apps that don't need
# precise timing, and use ControlFlow.Async for high-performance
# apps like game engines that need precise timing, at the cost
# of increased CPU usage.
app.controlFlow = ControlFlow.Wait
# Create a Pixie image
let image = newImage(680, 480)
for i in 0 ..< image.data.len:
image.data[i] = rgbx(255, 255, 255, 255) # Make the image fully white
var font = readFont("IBMPlexSans-Regular.ttf") # Replace this with a font path
font.size = 20
# Just add some text for fun :^)
image.fillText(font.typeset("Hello, surfer!", vec2(180, 180)), translate(vec2(10, 10)))
while not app.closureRequested:
let eventOpt = app.flushQueue()
if !eventOpt:
# If we have no event to consume, continue.
continue
let event = &eventOpt
case event.kind
of EventKind.RedrawRequested:
# Redrawing logic
let stride = image.width * sizeof(ColorRGBX)
# Wayland specific logic: Copy pixie image buffer to the mapped buffer
# that surfer allocated.
for y in 0 ..< image.height:
copyMem(
cast[pointer](cast[uint](app.pools.surfaceDest) + uint(y * stride)),
addr image.data[y * image.width],
stride,
)
app.markDamaged()
# Tell the compositor that we're ready to draw another frame, if it wishes so.
app.queueRedraw()
of EventKind.KeyboardFocusObtained:
echo "Keyboard focus on surface"
of EventKind.KeyboardFocusLost:
echo "Keyboard focus lost"
of EventKind.KeyReleased:
echo "Key released: " & $event.key.code
of EventKind.KeyPressed:
echo "Key pressed: " & $event.key.code
of EventKind.KeyRepeated:
echo "Key repeated: " & $event.key.code
else:
discard
when isMainModule: main()
roadmap
The items here are non-sequential. - [X] Software rendering support - [X] Keyboard input support (repeating is handled internally by Surfer, while respecting the compositor's repeat hints) - [X] Automatic libxkbcommon initialization - [X] Pointer input support - [X] OpenGL ES rendering support - [X] Layer shell support - [X] Idle inhibit support - [X] System bell support - [ ] Presentation time support - [ ] Tablet support - [X] Vulkan support - [X] Decoration mode support - [X] Cursor shape support - [X] Tearing Control support - [ ] Clipboard support - [X] Fractional scale support
distant roadmap
- [ ] win32 backend
- [ ] Cocoa backend
non-goals
- X11 support: It's an old protocol, the reference server (Xorg) is unmaintained, and Wayland is the future, so there's no point in supporting it anymore.