screenshots

Native screenshot command helpers for Windows, Linux, and macOS.

moonbit
native
screenshots
moon add justjavac/screenshots@0.1.2
Download zip
Author
Version
0.1.2
License
MIT
Last updated
2 months ago
Downloads
21

Dependencies

README

#justjavac/screenshots

Native API-backed screenshot helpers.

test {
let area = @screenshots.clamp_area({ x: -4, y: 8, width: 0, height: 120 })
inspect(area, content="{ x: 0, y: 8, width: 1, height: 120 }")
}

test {
let target = @screenshots.Area({ x: 10, y: 20, width: 300, height: 200 })
inspect(@screenshots.target_label(target), content="area-10-20-300x200")
}

#
CaptureArea

pub(all) struct CaptureArea {
x : Int
y : Int
width : Int
height : Int
} derive(Eq,
Debug
)

A rectangular region in desktop coordinates.

x and y describe the top-left corner. width and height describe the size in pixels. Use clamp_area before handing user input to platform screenshot APIs so negative coordinates become zero and empty dimensions become one pixel.

Example

test {
let area = @screenshots.clamp_area({ x: -8, y: 4, width: 0, height: 12 })
inspect(area, content="{ x: 0, y: 4, width: 1, height: 12 }")
}
impl Show for CaptureArea

#
CaptureTarget

pub(all) enum CaptureTarget {
AllDisplays
Display(Int)
Window(UInt64)
Area(CaptureArea)
} derive(Eq,
Debug
)

The desktop object to capture.

AllDisplays captures the whole desktop, Display(index) targets a display when the platform API supports it, Window(handle) targets an operating system window handle or id, and Area(area) captures a rectangular region. Window stores the handle as UInt64 so 64-bit native handles can be passed without truncation.

Example

test {
let target = @screenshots.Area({ x: 10, y: 20, width: 300, height: 200 })
inspect(@screenshots.target_label(target), content="area-10-20-300x200")
}

#
capture_to_file

fn capture_to_file(target : CaptureTarget, output_path : String) -> Bool

Capture a screenshot into a PNG file through the host operating-system API.

target selects the desktop object or rectangle to capture. output_path is converted with justjavac/ffi into null-terminated native buffers: Windows consumes the UTF-16 wide path, while macOS and Linux consume the UTF-8 path. The function returns true only when the platform API succeeds and the PNG file is written completely.

On Windows the backend uses Win32/GDI, on macOS it uses CoreGraphics and ImageIO, and on Linux it uses X11. Wayland sessions without an accessible X11 display return false because there is no single stable desktop-wide screenshot API to call directly.

#
clamp_area

fn clamp_area(area : CaptureArea) -> CaptureArea

Normalize a capture area into coordinates and dimensions accepted by native screenshot APIs.

Coordinates are clamped to 0. Width and height are clamped to 1, which keeps downstream API calls from producing empty rectangles. This is intentionally conservative: it preserves valid values exactly and only fixes values that desktop APIs commonly reject.

Example

test {
let area = @screenshots.clamp_area({ x: -10, y: 5, width: 0, height: -3 })
inspect(area, content="{ x: 0, y: 5, width: 1, height: 1 }")
}

#
intersect

fn intersect(a : CaptureArea, b : CaptureArea) -> CaptureArea?

Intersect two capture areas and return the overlapping rectangle.

The function uses the rectangles exactly as provided. Normalize user input with clamp_area first when you want negative coordinates or empty sizes to be corrected before computing the overlap.

Example

test {
debug_inspect(
@screenshots.intersect({ x: 0, y: 0, width: 10, height: 10 }, {
x: 4,
y: 3,
width: 10,
height: 2,
}),
content="Some({ x: 4, y: 3, width: 6, height: 2 })",
)
}

#
output_name

fn output_name(prefix : String, index : Int) -> String

Generate a deterministic PNG filename for a captured frame.

The prefix is preserved exactly so callers can decide whether to include a directory, timestamp, or target label. Negative indexes are normalized to zero to avoid accidental filenames like shot--1.png.

Example

test {
inspect(@screenshots.output_name("capture", 3), content="capture-3.png")
inspect(@screenshots.output_name("capture", -1), content="capture-0.png")
}

#
pixel_count

fn pixel_count(area : CaptureArea) -> Int

Return the number of pixels covered by a normalized capture area.

The input is first passed through clamp_area, so empty or negative dimensions still produce a useful one-pixel minimum.

Example

test {
inspect(
@screenshots.pixel_count({ x: 0, y: 0, width: 4, height: 3 }),
content="12",
)
inspect(
@screenshots.pixel_count({ x: 0, y: 0, width: 0, height: 3 }),
content="3",
)
}

#
target_label

fn target_label(target : CaptureTarget) -> String

Produce a stable label for a capture target.

Area targets are normalized before formatting so the label always matches the API-ready rectangle used by capture_to_file.

Example

test {
inspect(
@screenshots.target_label(Area({ x: -1, y: 5, width: 0, height: 4 })),
content="area-0-5-1x4",
)
}

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io