HSCanvas
TypeHSCanvas
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
Declaration
show() -> HSCanvas
Returns
HSCanvas
Self for chaining
hide() -> HSCanvas
Hide the canvas window (keeps it in memory; elements and window config are preserved)
Declaration
hide() -> HSCanvas
Returns
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.
Declaration
destroy() -> None
Returns
None
Example
c.destroy()
isShowing() -> boolean
Whether the canvas window is currently ordered onto the screen
Declaration
isShowing() -> boolean
Returns
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)
Declaration
isVisible() -> boolean
Returns
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
Declaration
isOccluded() -> boolean
Returns
boolean
`true` if the canvas is showing but fully occluded or off-screen
frame() -> object
The canvas window's current position and size
Declaration
frame() -> object
Returns
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
Declaration
setFrame(rect) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| rect | {[key: string]: any} | A `{x, y, w, h}` dictionary. Any keys left out keep their current value |
Returns
HSCanvas
Self for chaining
Example
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`.
Declaration
topLeft() -> object
Returns
object
An `{x, y}` dictionary
setTopLeft(point) -> HSCanvas
Move the canvas window without changing its size
Declaration
setTopLeft(point) -> HSCanvas
Parameters
| 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 |
Returns
HSCanvas
Self for chaining
Example
c.setTopLeft({x: 200, y: 800})
size() -> object
The canvas window's current size
Declaration
size() -> object
Returns
object
A `{w, h}` dictionary
setSize(dimensions) -> HSCanvas
Resize the canvas window without moving its top-left corner
Declaration
setSize(dimensions) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| dimensions | {[key: string]: any} | A `{w, h}` dictionary. Any keys left out keep their current value |
Returns
HSCanvas
Self for chaining
Example
c.setSize({w: 400, h: 300})
level(name) -> HSCanvas
Set the window level by name
Declaration
level(name) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| name | string | A level name from `hs.canvas.windowLevels` (e.g. `"floating"`, `"screenSaver"`) |
Returns
HSCanvas
Self for chaining
Example
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.
Declaration
levelValue(value) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| value | number | A raw numeric window level |
Returns
HSCanvas
Self for chaining
Example
c.levelValue(hs.canvas.windowLevels.screenSaver + 1)
behavior(name) -> HSCanvas
Set the window's Spaces/Exposé collection behavior to a single named behavior
Declaration
behavior(name) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| name | string | A behavior name from `hs.canvas.windowBehaviors` (e.g. `"canJoinAllSpaces"`) |
Returns
HSCanvas
Self for chaining
Example
c.behavior("canJoinAllSpaces")
behaviorList(names) -> HSCanvas
Set the window's Spaces/Exposé collection behavior to a combination of named behaviors
Declaration
behaviorList(names) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| names | string[] | Behavior names from `hs.canvas.windowBehaviors`, combined together |
Returns
HSCanvas
Self for chaining
Example
c.behaviorList(["canJoinAllSpaces", "stationary"])
behaviorValue(value) -> HSCanvas
Set the window's Spaces/Exposé collection behavior to a raw bitmask
Declaration
behaviorValue(value) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| value | number | A raw `NSWindow.CollectionBehavior` bitmask |
Returns
HSCanvas
Self for chaining
clickActivating(flag) -> HSCanvas
Set whether clicking the canvas activates the Hammerspoon app
Declaration
clickActivating(flag) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| flag | boolean | Pass `false` to prevent clicks on the canvas from bringing the app forward |
Returns
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.
Declaration
ignoreMouseEvents(flag) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| flag | boolean | Pass `true` to make the canvas fully click-through |
Returns
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.
Declaration
appendElements(elements) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| elements | [[String: Any]] | Array of element dictionaries (each needs at least a `type`) |
Returns
HSCanvas
Self for chaining
Example
c.appendElements([{ type: "circle", action: "fill", fillColor: { alpha: 1 } }])
insertElement(element, index) -> HSCanvas
Insert an element at a specific index
Declaration
insertElement(element, index) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| element | {[key: string]: any} | The element dictionary to insert |
| index | number | The index to insert at (clamped to the valid range) |
Returns
HSCanvas
Self for chaining
assignElement(element, index) -> HSCanvas
Replace the element at an index, or append if the index equals the current element count
Declaration
assignElement(element, index) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| element | {[key: string]: any} | The replacement element dictionary |
| index | number | The index to replace |
Returns
HSCanvas
Self for chaining
removeElement(index) -> HSCanvas
Remove the element at a specific index
Declaration
removeElement(index) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The index to remove |
Returns
HSCanvas
Self for chaining
removeLastElement() -> HSCanvas
Remove the last element
Declaration
removeLastElement() -> HSCanvas
Returns
HSCanvas
Self for chaining
replaceElements(elements) -> HSCanvas
Replace all elements on the canvas
Declaration
replaceElements(elements) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| elements | [[String: Any]] | The new full element list |
Returns
HSCanvas
Self for chaining
elementCount() -> number
The number of elements on the canvas
Declaration
elementCount() -> number
Returns
number
The current element count
canvasElements() -> object[]
All elements currently on the canvas
Declaration
canvasElements() -> object[]
Returns
object[]
Array of element dictionaries
elementKeys(index) -> string[]
The attribute keys present on an element
Declaration
elementKeys(index) -> string[]
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
Returns
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.
Declaration
elementAttribute(index, key) -> any
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
| key | string | The attribute key |
Returns
any
The attribute's current value, or `null` if not set
setElementAttribute(index, key, value) -> HSCanvas
Set a single attribute value on an element
Declaration
setElementAttribute(index, key, value) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
| key | string | The attribute key |
| value | any | The value to assign |
Returns
HSCanvas
Self for chaining
removeElementAttribute(index, key) -> HSCanvas
Remove a single attribute from an element
Declaration
removeElementAttribute(index, key) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
| key | string | The attribute key to remove |
Returns
HSCanvas
Self for chaining
elementBounds(index) -> object
The smallest rectangle enclosing an element's rendered shape
Declaration
elementBounds(index) -> object
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
Returns
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.
Declaration
minimumTextSize(index, text) -> object
Parameters
| 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` |
Returns
object
A `{w, h}` dictionary, or `{}` if `index` is out of bounds
Example
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"`).
Declaration
mouseCallback(callback) -> HSCanvas
Parameters
| 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 |
Returns
HSCanvas
Self for chaining
Example
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"`.
Declaration
canvasMouseEvents(down, up, enterExit, move) -> HSCanvas
Parameters
| 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 |
Returns
HSCanvas
Self for chaining
rotateElement(index, angle) -> HSCanvas
Rotate an element about its own bounding-box center
Declaration
rotateElement(index, angle) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
| angle | number | The rotation angle, in degrees |
Returns
HSCanvas
Self for chaining
rotateElementAroundPoint(index, angle, point) -> HSCanvas
Rotate an element about a specific point
Declaration
rotateElementAroundPoint(index, angle, point) -> HSCanvas
Parameters
| 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 |
Returns
HSCanvas
Self for chaining
setElementTransformation(index, matrix) -> HSCanvas
Apply a raw 2D affine transformation matrix to a single element
Declaration
setElementTransformation(index, matrix) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| index | number | The element index |
| matrix | {[key: string]: any} | A `{m11, m12, m21, m22, tX, tY}` matrix dictionary |
Returns
HSCanvas
Self for chaining
setTransformation(matrix) -> HSCanvas
Apply a raw 2D affine transformation matrix to the whole canvas
Declaration
setTransformation(matrix) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| matrix | {[key: string]: any} | A `{m11, m12, m21, m22, tX, tY}` matrix dictionary |
Returns
HSCanvas
Self for chaining
clearTransformation() -> HSCanvas
Remove the whole-canvas transformation set by `setTransformation()`
Declaration
clearTransformation() -> HSCanvas
Returns
HSCanvas
Self for chaining
imageFromCanvas() -> HSImage
Render the canvas's current contents to an image
Declaration
imageFromCanvas() -> HSImage
Returns
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()`.
Declaration
duplicate() -> HSCanvas
Returns
HSCanvas
A new HSCanvas
setAccessibilitySubrole(subrole) -> HSCanvas
Set the accessibility subrole reported for this canvas's window
Declaration
setAccessibilitySubrole(subrole) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| subrole | string | The accessibility subrole string |
Returns
HSCanvas
Self for chaining
draggingCallback(callback) -> HSCanvas
Set a callback fired when files or text are dropped onto the canvas
Declaration
draggingCallback(callback) -> HSCanvas
Parameters
| Name | Type | Description |
|---|---|---|
| callback | function | Called with the dropped file paths, or a single-element array containing dropped text |
Returns
HSCanvas
Self for chaining