A low-level, absolutely-positioned drawing surface*
hs.canvas mirrors v1 Hammerspoon's hs.canvas module: elements are plain JS
objects (mirroring v1's Lua tables) describing shapes (rectangle, circle,
oval, text) with a fill/stroke/strokeAndFill/clip/build/skip action
pipeline. This is a different tool from hs.ui, which is a SwiftUI stack/layout
builder for app-like interfaces -- reach for hs.canvas when you need absolute
positioning, clipped/composited shapes, or direct window-level/Spaces control.
Coordinate systems -- read this before positioning elements
A canvas's window position (create({x, y, w, h}), and any later x/y you
y = 0 is the bottom of the screen, and y increases upward. This matches
hs.ui.window.
But element content positioned inside a canvas -- every frame, center, and
y = 0 is the top of the canvas, and y increases downward. These two coordinate
senses are independent of each other and easy to conflate, especially when a script
computes an element's position from the same screen geometry it used for the
window's own placement. If a shape appears vertically mirrored from where you
expect, this mismatch is the first thing to check.
hs.canvas
A low-level, absolutely-positioned drawing surface*
hs.canvasmirrors v1 Hammerspoon'shs.canvasmodule: elements are plain JS objects (mirroring v1's Lua tables) describing shapes (rectangle,circle,oval,text) with afill/stroke/strokeAndFill/clip/build/skipaction pipeline. This is a different tool fromhs.ui, which is a SwiftUI stack/layout builder for app-like interfaces -- reach forhs.canvaswhen you need absolute positioning, clipped/composited shapes, or direct window-level/Spaces control.Coordinate systems -- read this before positioning elements
A canvas's window position (
create({x, y, w, h}), and any laterx/yyouy = 0is the bottom of the screen, andyincreases upward. This matcheshs.ui.window. But element content positioned inside a canvas -- everyframe,center, andy = 0is the top of the canvas, andyincreases downward. These two coordinate senses are independent of each other and easy to conflate, especially when a script computes an element's position from the same screen geometry it used for the window's own placement. If a shape appears vertically mirrored from where you expect, this mismatch is the first thing to check.Example: a rounded screen corner overlay