# Peter Griffin prank (Rust remake)
A tiny prank desktop app: a borderless 397x319 window shows a Peter Griffin
image and a **Close** button. The button does not close anything — it opens
50 windows (800x450, same image stretched) at random positions on screen, one
every 100 ms, until the desktop is buried.
This is a Rust port (eframe/egui) of an original .NET WinForms executable
(`Peter.exe`). Window sizes, image placement, the "Close" button and the
50-popup volley match the original; popup placement is now randomised instead
of stacking.
## Run it
The manifest holds the whole story:
```toml
install = "cargo build --release"
run = "bin\\peter.exe || bin/peter || cargo run --release"
```
`nd run <slug>` shells that out (`sh -c` on Unix, `cmd /C` on Windows), so:
```bash
nd run peter-griffin-prank # prebuilt binary for this OS
cargo run --release # force a source build
```
How the chain resolves:
| Shell | First branch | Result |
|---|---|---|
| cmd (Windows) | `bin\peter.exe` | runs the Windows build — **backslashes are required**: cmd splits `bin/peter` into command `bin` plus switch `/peter` |
| sh (Linux/macOS) | `bin\peter.exe` → `binpeter.exe` | not found (one harmless line), falls through to `bin/peter`, the native ELF |
| either, no prebuilt | `cargo run --release` | builds and runs from source (needs rustc 1.95+) |
Windows without Rust still works — the first branch never needs cargo.
### Prebuilt binaries
| Platform | File | Notes |
|---|---|---|
| Linux x86-64 | `bin/peter` | needs GL/Vulkan, X11 or Wayland |
| Windows x86-64 | `bin/peter.exe` | Windows 10+ (UCRT), DirectX 12 or Vulkan |
They can also be run directly. Both were verified locally: the Linux one
natively, the Windows one under Wine (window appears at 397x319 as expected).
## Build from source
Requires **rustc 1.95+** (the eframe/egui 0.37 family declares that MSRV):
```bash
rustup update stable
cargo build --release # -> target/release/peter
cargo run --release
```
### Cross-compiling the Windows build on Linux
Needs a Linux-hosted MinGW-w64 toolchain (Debian/Ubuntu:
`gcc-mingw-w64-x86-64`; Arch: `mingw-w64-gcc` + `mingw-w64-binutils`, which also
provides the `x86_64-w64-mingw32-dlltool` that `rustc` needs for the `windows`
crates' raw-dylib imports). Zig's bundled MinGW is *not* enough — its sysroot
lacks `libpthread.a`/`msvcrt` that Rust's `windows-gnu` link line expects.
```bash
rustup target add x86_64-pc-windows-gnu
cargo build --release --target x86_64-pc-windows-gnu
cp target/x86_64-pc-windows-gnu/release/peter.exe bin/peter.exe
cp target/release/peter bin/peter # refresh the Linux build too
```
Release builds use the Windows GUI subsystem (`#![cfg_attr(not(debug_assertions),
windows_subsystem = "windows")]`), so no console window appears.
## Notes
- The main window is borderless and centred on the monitor at startup.
- Popups get explicit random positions. Wayland compositors ignore
client-requested window positions, so the app hides
`WAYLAND_DISPLAY`/`WAYLAND_SOCKET` at startup to make winit use
X11/XWayland. Set `PETER_KEEP_WAYLAND=1` to keep native Wayland — popups will
then be placed by the compositor (usually all in the same spot).
- There is no network, filesystem or persistence code; the app only creates
windows.
## Layout (taken from the original WinForms forms)
| Element | Geometry |
|---|---|
| main window | 397x319, undecorated, centred |
| face image | (12,43) 373x171, stretched |
| "Close" button | (149,273) 75x23 |
| popup window | 800x450, title "Form2", image stretched |
| popup timing | 50 windows, 100 ms apart, random positions |