# TNCat A little cat that wanders along the bottom edge of the screen, sits down, grooms itself, stretches, dashes off and takes naps. Every now and then a curled steel chip skitters past and the cat goes after it. Drag it around, tap it to pet it, and it purrs. It announces what it is doing in the machine's own language: `G00` when it sprints, `G01` when it strolls, `M08` while it washes, `G28` when it stretches back to reference, `M30` when it goes to sleep. The name is `TNC` plus `cat`, because the intended home is a HEIDENHAIN control (TNC7, TNC 640). Primary target is therefore **Linux / X11**; development happens on macOS and both are supported by the same code. Inspired by [workcat.app](https://workcat.app/en/), rebuilt from scratch as a plain Qt 6 / QML project. ## Layout | Path | Purpose | |---|---| | `CMakeLists.txt` | `qt_add_executable` + `qt_add_qml_module` (URI `TNCat`), macOS bundle, `.desktop` file on Linux | | `src/main.cpp` | Wires `AppSettings` and `CatController` into the QML engine, warns on Wayland | | `src/catcontroller.*` | Mood machine (walk, run, sit, groom, stretch, sleep, love, alert, chase, bat), movement tick, chip chase, cursor tracking | | `src/appsettings.*` | `QSettings`-backed coat, size, pace, ground line, eye tracking, pet counter | | `src/platforminfo.*` | QML singleton `Platform`: platform name plus the X11 escape hatches | | `src/traycontroller.*` | Tray icon and menu, silently skipped when the desktop has no tray | | `qml/Main.qml` | Non-visual root that picks the window layout for the platform | | `qml/CatWindow.qml`, `qml/ChipWindow.qml` | One small window each, positioned by the app. X11, macOS, Windows | | `qml/OverlayWindow.qml` | One screen-filling click-through window holding both. Wayland | | `qml/Cat.qml` | The drawing: rounded primitives plus `Shape` paths for tail, ears and mouth | | `qml/Chip.qml` | The curled chip, a stroked `Shape` spiral | | `qml/SettingsWindow.qml` | Coat swatches, size, pace, ground line, eye tracking, codes, chips, tricks | The cat is drawn in a fixed 100 x 90 design space and scaled by `width / 100`, so every size setting stays crisp. There are no image assets, which keeps the whole thing to one binary plus Qt. ## Build macOS with the Qt online installer: ```bash ~/Qt/6.11.1/macos/bin/qt-cmake -S . -B build -G Ninja -DCMAKE_MAKE_PROGRAM=$HOME/Qt/Tools/Ninja/ninja ``` Linux with distribution Qt packages: ```bash cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release ``` ```bash cmake --build build ``` Needs Qt 6.5 or newer. Required modules: Core, Gui, Quick, QuickControls2, Widgets. Widgets is only there because `QSystemTrayIcon` needs it for its context menu. ## Environment switches | Variable | Effect | |---|---| | `TNCAT_X11_BYPASS=1` | Adds `Qt::X11BypassWindowManagerHint`, making an override-redirect window. Use when the window manager refuses to keep the cat on top or shows it in the taskbar. | | `TNCAT_OVERLAY=1` | Forces the screen-filling overlay layout that Wayland needs, for testing it on X11. | | `TNCAT_OPAQUE=1` | Paints a solid background instead of relying on transparency. Use when no compositor runs and the cat sits in a black box. | | `TNCAT_POSE=Sitting` | Freezes the cat in one mood. Handy for screenshots. Accepts any `CatController::Mood` name. | | `QT_QUICK_BACKEND=software` | Qt Quick's software rasteriser, for machines without a usable OpenGL driver. `Shape` falls back to its geometry renderer on its own. | ## Two window layouts On X11, macOS and Windows the cat and the chip each get their own small, frameless, always-on-top window, and the app moves those windows around. Nothing else on screen is covered and no clicks are intercepted. Wayland does not let a client place its own window, so that layout cannot work there. In overlay mode the app instead opens one screen-filling transparent window, moves the cat inside it, and restricts the window's input region to the cat's rectangle with `QWindow::setMask`, so every click outside the cat lands on whatever is behind. The mask is refreshed about 30 times a second while the cat walks. Overlay mode switches on automatically on Wayland. `TNCAT_OVERLAY=1` turns it on anywhere for testing. It is not the default elsewhere because macOS ignores the input mask, which would make the overlay swallow every click on the desktop. ## Running on a HEIDENHAIN control Untested on real hardware so far. What the code already does for that target: - **X11 today, Wayland later.** Both layouts are in the build; the platform picks one at startup. - **No tray required.** If the desktop has no status-notifier host, the tray icon is skipped and the cat itself stays the entry point: long-press or right-click opens the settings window. - **Touch works without hover.** Tap pets the cat, drag picks it up. The blush on hover is a mouse-only extra, not a requirement. - **Ground line setting.** The cat normally stands on the bottom of the available screen area. On a control whose lower edge carries softkeys, raise the ground line in the settings so the cat walks above them. What still needs checking on the actual machine: - **Qt version and libraries on HEROS.** Build against what the control has, or ship a self-contained bundle with the Qt libraries next to the binary. Building on a newer distribution than the control runs will fail at load time on glibc. - **Graphics stack.** If Qt Quick cannot get an OpenGL context, start with `QT_QUICK_BACKEND=software`. The drawing is simple enough for that path. - **Window management.** The NC user interface runs fullscreen. Try the default flags first, then `TNCAT_X11_BYPASS=1` if the cat disappears behind it. - **Installing anything on a control is subject to your site's rules.** Keep the cat away from anything the operator needs to read, and clear it with whoever administers the machine before it runs on production hardware. ## Interaction | Input | Result | |---|---| | Click or tap | Pet the cat, it closes its eyes and purrs | | Drag | Pick the cat up and put it somewhere else | | Hover | Blush and purr wiggle | | Double-click or right-click | Settings window | | Tray menu | Tricks, nap toggle, settings, quit |