Documentation
¶
Overview ¶
Package cocoa is the pure-Go (CGO-free, via purego) macOS AppKit windowing backend for the go-widgets toolkit. It opens a real NSWindow with a content NSView, blits the toolkit's RGBA framebuffer into it through an NSBitmapImageRep in -drawRect:, and routes native NSEvent mouse/scroll/key input into toolkit.Event, so a go-widgets widget tree runs on a macOS desktop exactly as it does on X11, Wayland or in the browser/wasm host.
The Objective-C runtime is reached through the fleet's shared bridge github.com/go-macos/objc (Send/RegisterClass/GetClass/NSString/GoString/…), itself layered over github.com/ebitengine/purego — no cgo — so the whole module builds and links with CGO_ENABLED=0.
This file is the SOVEREIGN, OS-INDEPENDENT half: the NSEvent→toolkit.Event mapping (key decode, modifier decode, button/wheel mapping), the flipped-view coordinate maths and the damage-rect→dirty-rect conversion, all expressed over plain Go values with a single toolkit dependency (the event model). It carries NO objc/purego/unsafe dependency, so it builds — and is unit-tested to 100% — on every GOOS, mirroring internal/wasmbox's protocol.go. The thin AppKit glue that actually creates the NSWindow, presents the bitmap and pumps the run loop lives in cocoa_darwin.go (//go:build darwin) and drives everything here.
Index ¶
- func DecodeKey(keyCode uint16, chars string) (name string, r rune)
- func DecodeMods(flags uint64) (shift, ctrl bool)
- func DefaultContentSize(visW, visH float64) (w, h int)
- func DirtyRect(r toolkit.Rect, scale float64) (x, y, w, h float64)
- func MapKey(keyCode uint16, chars string, shift, ctrl, press bool) []toolkit.Event
- func MapMouseDown(x, y int, shift, ctrl bool) toolkit.Event
- func MapMouseMove(x, y int, buttonHeld, shift, ctrl bool) toolkit.Event
- func MapMouseUp(x, y int, shift, ctrl bool) toolkit.Event
- func MapScroll(x, y int, deltaY float64, shift, ctrl bool) toolkit.Event
- func ViewCoords(px, py, boundsHPoints, scale float64) (int, int)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeKey ¶
DecodeKey maps an NSEvent keyDown/keyUp to either a symbolic key NAME (DOM-style: "Enter", "ArrowLeft", …, exactly the names the toolkit widgets match and the wasmbox backend emits) or a printable rune. keyCode is checked first so Return/Escape/Delete/arrows never leak through as control or private-use runes. A result of ("", 0) means the key carries nothing to deliver (an unmapped or non-printable key).
chars is the event's -charactersIgnoringModifiers value; only a single genuine printable rune (>= 0x20, not DEL, and outside the NSFunctionKey private-use range U+F700..U+F8FF, where AppKit reports arrows/F-keys) is accepted as text — the identical filter the reader precedent applies.
func DecodeMods ¶
DecodeMods splits an NSEvent modifierFlags mask into the toolkit's Shift/Ctrl booleans. Shift maps from NSEventModifierFlagShift; Ctrl maps from EITHER Control OR Command, so a ⌘-based macOS shortcut reaches a widget with the same Ctrl flag an X11/Wayland Control chord would — keeping the toolkit's platform-neutral Ctrl shortcut semantics (Ctrl+C / Cmd+C both land as Ctrl).
func DefaultContentSize ¶ added in v0.6.1
DefaultContentSize picks a readable default window content size, in LOGICAL points, from the main screen's visible frame (visW×visH, also in points). It takes defaultScreenFraction of the visible area and clamps each axis to the [min,max] readability band, then to the visible extent so the window never exceeds the usable screen. When the screen size is unknown (visW or visH ≤ 0) it returns the fixed fallback. The result is always ≥ 1×1 and ≤ the visible frame, so a defaulted window is legible without manual sizing.
func DirtyRect ¶
DirtyRect converts a damage rectangle in DEVICE pixels (top-left origin, the space RenderDamaged reports and the framebuffer uses) to a rectangle in the flipped content view's POINT coordinates, ready for -setNeedsDisplayInRect:. Because the content view is flipped (isFlipped → top-left origin, matching the buffer), only a scale division is needed — no Y flip. The returned rectangle is clamped to be non-negative and is expanded to whole points (floor origin, ceil far edge) so a sub-point damage rect never leaves a seam.
func MapKey ¶
MapKey turns a decoded keyDown/keyUp into the toolkit event(s) it produces, mirroring the X11 and wasmbox backends EXACTLY:
- a named key yields a single EventKeyDown (press) / EventKeyUp (release) carrying the name in Code;
- a printable key yields EventKeyDown+EventChar on press (Char being the committed rune) and a single EventKeyUp on release — the same press/char split the X11 backend performs;
- a key that decodes to nothing (unmapped / pure modifier) delivers nothing.
The result is nil when the key maps to no toolkit event.
func MapMouseDown ¶
MapMouseDown turns a left/other mouse-button press at the given view-local pixel into an EventClick, mirroring the X11 ButtonPress (buttons 1–3 → click) mapping. macOS delivers separate selectors per button; the backend routes all of them here.
func MapMouseMove ¶
MapMouseMove turns a pointer move into a drag (a button held) or a plain hover move, per buttonHeld — the same drag-vs-move split the X11/Wayland backends derive from the event's button-state mask (AppKit instead delivers -mouseMoved: vs -mouseDragged:, which the glue collapses into buttonHeld).
func MapMouseUp ¶
MapMouseUp turns a mouse-button release into an EventMouseUp.
func MapScroll ¶
MapScroll turns an AppKit -scrollingDeltaY into an EventScroll whose Delta is normalised to the toolkit's ±1 row step. AppKit's scrollingDeltaY is POSITIVE when the content is pushed up (a natural upward swipe); the toolkit's Delta is POSITIVE to scroll down/forward, so the sign is inverted — matching the browser/wheel convention the X11 and wasmbox backends use. A zero delta yields a Delta-0 EventScroll (harmless; scrollable widgets clamp it), so the mapping is total.
func ViewCoords ¶
ViewCoords converts an NSEvent -locationInWindow (window base coordinates, which are ALWAYS bottom-left origin in points, even in a flipped view) to device-pixel coordinates with a top-left origin — the coordinate space the toolkit framebuffer and every toolkit.Event uses.
boundsHPoints is the content view's height in points; scale is the window's backing scale factor (1 on a non-Retina display, 2 on Retina). The Y axis is flipped (boundsHPoints - py) to move the origin to the top, then both axes are multiplied by scale to reach device pixels.
Types ¶
This section is empty.