API Docs

HSCanvas

A single canvas window: an absolutely-positioned, low-level drawing surface mirroring v1 Hammerspoon's hs.canvas. Elements are plain JS objects (matching v1's Lua tables) added with appendElements() and mutated in place with setElementAttribute()/elementAttribute(). Supports the same fill/stroke/ strokeAndFill/clip/build/skip action pipeline as v1, including the build+clip+reversePath technique used to punch holes in shapes (see hs.canvas.windowLevels/hs.canvas.windowBehaviors for the window-level/Spaces controls needed alongside this for overlay-style canvases).

Example

const c = hs.canvas.create({x: 100, y: 100, w: 200, h: 200})
c.appendElements([
    { type: "rectangle", action: "fill", fillColor: { red: 0.2, green: 0.5, blue: 0.9, alpha: 1 } }
])
c.show()

Properties

This type has no properties.

Methods

show() -> HSCanvas

Show the canvas window
show() -> HSCanvas
HSCanvas
Self for chaining

hide() -> HSCanvas

Hide the canvas window (keeps it in memory; elements and window config are preserved)
hide() -> HSCanvas
HSCanvas
Self for chaining

destroy() -> None

Destroy the canvas window and release its resources Named `destroy()` rather than v1's `delete()` -- `delete` cannot be used as a JavaScriptCore-exported method name in this codebase's bridging layer.
destroy() -> None
None
c.destroy()

isShowing() -> boolean

Whether the canvas window is currently ordered onto the screen
isShowing() -> boolean
boolean
`true` if the canvas has been shown and not hidden or destroyed

isVisible() -> boolean

Whether the canvas is showing AND at least partially visible (not fully occluded or off-screen)
isVisible() -> boolean
boolean
`true` if the canvas is showing and at least partially on-screen

isOccluded() -> boolean

Whether the canvas is hidden behind other windows, or off-screen entirely
isOccluded() -> boolean
boolean
`true` if the canvas is showing but fully occluded or off-screen

frame() -> object

The canvas window's current position and size
frame() -> object
object
A `{x, y, w, h}` dictionary, in the same unflipped AppKit screen coordinates as `create()`

setFrame(rect) -> HSCanvas

Move and/or resize the canvas window
setFrame(rect) -> HSCanvas
Name Type Description
rect {[key: string]: any} A `{x, y, w, h}` dictionary. Any keys left out keep their current value
HSCanvas
Self for chaining
c.setFrame({x: 200, y: 200, w: 300, h: 300})

topLeft() -> object

The canvas window's current top-left corner the point at the window's highest `y` (its screen-visual top), not `y = 0`.
topLeft() -> object
object
An `{x, y}` dictionary

setTopLeft(point) -> HSCanvas

Move the canvas window without changing its size
setTopLeft(point) -> HSCanvas
Name Type Description
point {[key: string]: any} An `{x, y}` dictionary giving the new top-left corner. Any keys left out keep their current value
HSCanvas
Self for chaining
c.setTopLeft({x: 200, y: 800})

size() -> object

The canvas window's current size
size() -> object
object
A `{w, h}` dictionary

setSize(dimensions) -> HSCanvas

Resize the canvas window without moving its top-left corner
setSize(dimensions) -> HSCanvas
Name Type Description
dimensions {[key: string]: any} A `{w, h}` dictionary. Any keys left out keep their current value
HSCanvas
Self for chaining
c.setSize({w: 400, h: 300})

level(name) -> HSCanvas

Set the window level by name
level(name) -> HSCanvas
Name Type Description
name string A level name from `hs.canvas.windowLevels` (e.g. `"floating"`, `"screenSaver"`)
HSCanvas
Self for chaining
c.level("floating")

levelValue(value) -> HSCanvas

Set the window level to a raw numeric value Split out from `level(_:)` (rather than accepting a string-or-number union) because JSExport parameters must have a single concrete type -- see `hs.canvas.windowLevels`, which exposes raw numeric values (not opaque name strings) so scripts can do arithmetic on them, matching v1 behavior.
levelValue(value) -> HSCanvas
Name Type Description
value number A raw numeric window level
HSCanvas
Self for chaining
c.levelValue(hs.canvas.windowLevels.screenSaver + 1)

behavior(name) -> HSCanvas

Set the window's Spaces/Exposé collection behavior to a single named behavior
behavior(name) -> HSCanvas
Name Type Description
name string A behavior name from `hs.canvas.windowBehaviors` (e.g. `"canJoinAllSpaces"`)
HSCanvas
Self for chaining
c.behavior("canJoinAllSpaces")

behaviorList(names) -> HSCanvas

Set the window's Spaces/Exposé collection behavior to a combination of named behaviors
behaviorList(names) -> HSCanvas
Name Type Description
names string[] Behavior names from `hs.canvas.windowBehaviors`, combined together
HSCanvas
Self for chaining
c.behaviorList(["canJoinAllSpaces", "stationary"])

behaviorValue(value) -> HSCanvas

Set the window's Spaces/Exposé collection behavior to a raw bitmask
behaviorValue(value) -> HSCanvas
Name Type Description
value number A raw `NSWindow.CollectionBehavior` bitmask
HSCanvas
Self for chaining

clickActivating(flag) -> HSCanvas

Set whether clicking the canvas activates the Hammerspoon app
clickActivating(flag) -> HSCanvas
Name Type Description
flag boolean Pass `false` to prevent clicks on the canvas from bringing the app forward
HSCanvas
Self for chaining

ignoreMouseEvents(flag) -> HSCanvas

Set whether the canvas window ignores all mouse events, passing clicks through to whatever is behind it This is a capability beyond v1's `hs.canvas` API surface (not a literal v1 method name) -- v1 has no direct equivalent for full click pass-through.
ignoreMouseEvents(flag) -> HSCanvas
Name Type Description
flag boolean Pass `true` to make the canvas fully click-through
HSCanvas
Self for chaining

appendElements(elements) -> HSCanvas

Append one or more elements to the end of the canvas Element `frame`/`center`/`coordinates` values are y-down (`y = 0` at the top of the canvas) -- a different sense from the canvas *window's* own `x`/`y` position, which is unflipped AppKit screen coordinates. See `hs.canvas`'s module-level docs for the full explanation.
appendElements(elements) -> HSCanvas
Name Type Description
elements [[String: Any]] Array of element dictionaries (each needs at least a `type`)
HSCanvas
Self for chaining
c.appendElements([{ type: "circle", action: "fill", fillColor: { alpha: 1 } }])

insertElement(element, index) -> HSCanvas

Insert an element at a specific index
insertElement(element, index) -> HSCanvas
Name Type Description
element {[key: string]: any} The element dictionary to insert
index number The index to insert at (clamped to the valid range)
HSCanvas
Self for chaining

assignElement(element, index) -> HSCanvas

Replace the element at an index, or append if the index equals the current element count
assignElement(element, index) -> HSCanvas
Name Type Description
element {[key: string]: any} The replacement element dictionary
index number The index to replace
HSCanvas
Self for chaining

removeElement(index) -> HSCanvas

Remove the element at a specific index
removeElement(index) -> HSCanvas
Name Type Description
index number The index to remove
HSCanvas
Self for chaining

removeLastElement() -> HSCanvas

Remove the last element
removeLastElement() -> HSCanvas
HSCanvas
Self for chaining

replaceElements(elements) -> HSCanvas

Replace all elements on the canvas
replaceElements(elements) -> HSCanvas
Name Type Description
elements [[String: Any]] The new full element list
HSCanvas
Self for chaining

elementCount() -> number

The number of elements on the canvas
elementCount() -> number
number
The current element count

canvasElements() -> object[]

All elements currently on the canvas
canvasElements() -> object[]
object[]
Array of element dictionaries

elementKeys(index) -> string[]

The attribute keys present on an element
elementKeys(index) -> string[]
Name Type Description
index number The element index
string[]
Array of attribute key names

elementAttribute(index, key) -> any

Get a single attribute value from an element Returns `Any?` (mirroring `hs.userdefaults.get()`) rather than a concrete Swift type because an element attribute's value is genuinely heterogeneous -- a string, number, boolean, nested object, or array, matching v1's dynamically-typed Lua table values.
elementAttribute(index, key) -> any
Name Type Description
index number The element index
key string The attribute key
any
The attribute's current value, or `null` if not set

setElementAttribute(index, key, value) -> HSCanvas

Set a single attribute value on an element
setElementAttribute(index, key, value) -> HSCanvas
Name Type Description
index number The element index
key string The attribute key
value any The value to assign
HSCanvas
Self for chaining

removeElementAttribute(index, key) -> HSCanvas

Remove a single attribute from an element
removeElementAttribute(index, key) -> HSCanvas
Name Type Description
index number The element index
key string The attribute key to remove
HSCanvas
Self for chaining

elementBounds(index) -> object

The smallest rectangle enclosing an element's rendered shape
elementBounds(index) -> object
Name Type Description
index number The element index
object
A `{x, y, w, h}` dictionary

minimumTextSize(index, text) -> object

The smallest size that can fully render a string of text, using a text element's font attributes (`textFont`/`textSize`/`textWeight`/`textDesign`/`textItalic`) Mirrors v1's `hs.canvas:minimumTextSize()`. Multi-line strings (separated by `\n`) are measured correctly -- the height covers every line and the width is the longest line's width, not a fixed single-line size.
minimumTextSize(index, text) -> object
Name Type Description
index number The index of a text element in the canvas whose font attributes to measure with
text string The string to measure -- it doesn't need to match the element's own `text`
object
A `{w, h}` dictionary, or `{}` if `index` is out of bounds
c.appendElements([{ type: "text", text: "placeholder", textFont: "Menlo-Bold", textSize: 24 }])
const size = c.minimumTextSize(0, "Hello\nWorld")
c.setElementAttribute(0, "frame", { x: 10, y: 10, w: size.w, h: size.h })

mouseCallback(callback) -> HSCanvas

Set the callback fired for tracked mouse events Fires for elements with `trackMouseDown`/`trackMouseUp`/`trackMouseEnterExit`/ `trackMouseMove` set to `true` in their element dictionary, and for whole-canvas regions enabled via `canvasMouseEvents()` (delivered with id `"_canvas"`).
mouseCallback(callback) -> HSCanvas
Name Type Description
callback function A JavaScript function called with the canvas, the event name (`"mouseDown"`/`"mouseUp"`/`"mouseEnter"`/`"mouseExit"`/`"mouseMove"`), the tracked element's id, and the event's x/y coordinates
HSCanvas
Self for chaining
c.appendElements([{ type: "circle", action: "fill", trackMouseDown: true, id: "dot" }])
c.mouseCallback((canvas, message, id, x, y) => console.log(message, id, x, y))

canvasMouseEvents(down, up, enterExit, move) -> HSCanvas

Enable whole-canvas mouse tracking for regions not covered by any individually tracked element. Delivered through `mouseCallback()` with id `"_canvas"`.
canvasMouseEvents(down, up, enterExit, move) -> HSCanvas
Name Type Description
down boolean Track mouse-down events
up boolean Track mouse-up events
enterExit boolean Track mouse enter/exit events
move boolean Track mouse-move events
HSCanvas
Self for chaining

rotateElement(index, angle) -> HSCanvas

Rotate an element about its own bounding-box center
rotateElement(index, angle) -> HSCanvas
Name Type Description
index number The element index
angle number The rotation angle, in degrees
HSCanvas
Self for chaining

rotateElementAroundPoint(index, angle, point) -> HSCanvas

Rotate an element about a specific point
rotateElementAroundPoint(index, angle, point) -> HSCanvas
Name Type Description
index number The element index
angle number The rotation angle, in degrees
point {[key: string]: any} A `{x, y}` dictionary giving the pivot point
HSCanvas
Self for chaining

setElementTransformation(index, matrix) -> HSCanvas

Apply a raw 2D affine transformation matrix to a single element
setElementTransformation(index, matrix) -> HSCanvas
Name Type Description
index number The element index
matrix {[key: string]: any} A `{m11, m12, m21, m22, tX, tY}` matrix dictionary
HSCanvas
Self for chaining

setTransformation(matrix) -> HSCanvas

Apply a raw 2D affine transformation matrix to the whole canvas
setTransformation(matrix) -> HSCanvas
Name Type Description
matrix {[key: string]: any} A `{m11, m12, m21, m22, tX, tY}` matrix dictionary
HSCanvas
Self for chaining

clearTransformation() -> HSCanvas

Remove the whole-canvas transformation set by `setTransformation()`
clearTransformation() -> HSCanvas
HSCanvas
Self for chaining

imageFromCanvas() -> HSImage

Render the canvas's current contents to an image
imageFromCanvas() -> HSImage
HSImage
An HSImage snapshot of the canvas, or `null` if it could not be rendered

duplicate() -> HSCanvas

Create an independent copy of this canvas, with the same frame, elements, and window configuration Named `duplicate()` rather than v1's `copy()` -- this codebase's conventions forbid method names starting with `copy` (an ARC/ObjC hazard), the same rule that renamed `new()` to `create()`.
duplicate() -> HSCanvas
HSCanvas
A new HSCanvas

setAccessibilitySubrole(subrole) -> HSCanvas

Set the accessibility subrole reported for this canvas's window
setAccessibilitySubrole(subrole) -> HSCanvas
Name Type Description
subrole string The accessibility subrole string
HSCanvas
Self for chaining

draggingCallback(callback) -> HSCanvas

Set a callback fired when files or text are dropped onto the canvas
draggingCallback(callback) -> HSCanvas
Name Type Description
callback function Called with the dropped file paths, or a single-element array containing dropped text
HSCanvas
Self for chaining