usecomputer 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/zig/src/lib.zig CHANGED
@@ -197,10 +197,6 @@ fn failData(comptime T: type, command: []const u8, code: []const u8, message: []
197
197
  };
198
198
  }
199
199
 
200
- fn todoNotImplemented(command: []const u8) CommandResult {
201
- return failCommand(command, "TODO_NOT_IMPLEMENTED", "TODO not implemented");
202
- }
203
-
204
200
  pub const Point = struct {
205
201
  x: f64,
206
202
  y: f64,
@@ -1187,12 +1183,12 @@ pub fn windowList() DataResult([]const u8) {
1187
1183
  }
1188
1184
 
1189
1185
  pub fn clipboardGet() DataResult([]const u8) {
1190
- return failData([]const u8, "clipboard-get", "TODO_NOT_IMPLEMENTED", "TODO not implemented: clipboard-get");
1186
+ return failData([]const u8, "clipboard-get", "NOT_SUPPORTED", "clipboard-get is not supported on this platform");
1191
1187
  }
1192
1188
 
1193
1189
  pub fn clipboardSet(input: ClipboardSetInput) CommandResult {
1194
1190
  _ = input;
1195
- return todoNotImplemented("clipboard-set");
1191
+ return failCommand("clipboard-set", "NOT_SUPPORTED", "clipboard-set is not supported on this platform");
1196
1192
  }
1197
1193
 
1198
1194
  pub fn typeText(input: TypeTextInput) CommandResult {
@@ -2024,6 +2020,127 @@ fn writeScreenshotPng(input: struct {
2024
2020
  }
2025
2021
  }
2026
2022
 
2023
+ /// Draw a red crosshair+circle debug marker on an existing PNG file (macOS only).
2024
+ /// Reads the PNG, draws the marker at (x, y) in image coordinates, writes back.
2025
+ pub fn drawMarkerOnPng(input: struct {
2026
+ path: []const u8,
2027
+ x: f64,
2028
+ y: f64,
2029
+ imageWidth: f64,
2030
+ imageHeight: f64,
2031
+ }) CommandResult {
2032
+ if (builtin.target.os.tag != .macos) {
2033
+ return failCommand("drawMarkerOnPng", "UNSUPPORTED_PLATFORM", "debug-point image overlay is only supported on macOS");
2034
+ }
2035
+
2036
+ // Load the existing PNG
2037
+ const path_as_u8: [*]const u8 = @ptrCast(input.path.ptr);
2038
+ const file_url = c.CFURLCreateFromFileSystemRepresentation(
2039
+ null,
2040
+ path_as_u8,
2041
+ @as(c_long, @intCast(input.path.len)),
2042
+ 0,
2043
+ );
2044
+ if (file_url == null) return failCommand("drawMarkerOnPng", "LOAD_FAILED", "failed to create file URL");
2045
+ defer c.CFRelease(file_url);
2046
+
2047
+ const source = c.CGImageSourceCreateWithURL(file_url, null);
2048
+ if (source == null) return failCommand("drawMarkerOnPng", "LOAD_FAILED", "failed to load PNG");
2049
+ defer c.CFRelease(source);
2050
+
2051
+ const image = c.CGImageSourceCreateImageAtIndex(source, 0, null);
2052
+ if (image == null) return failCommand("drawMarkerOnPng", "LOAD_FAILED", "failed to decode PNG image");
2053
+ defer c.CFRelease(image);
2054
+
2055
+ const w = c.CGImageGetWidth(image);
2056
+ const h = c.CGImageGetHeight(image);
2057
+
2058
+ // Create bitmap context
2059
+ const color_space = c.CGColorSpaceCreateDeviceRGB();
2060
+ if (color_space == null) return failCommand("drawMarkerOnPng", "DRAW_FAILED", "failed to create color space");
2061
+ defer c.CFRelease(color_space);
2062
+
2063
+ const ctx = c.CGBitmapContextCreate(
2064
+ null,
2065
+ w,
2066
+ h,
2067
+ 8,
2068
+ 0,
2069
+ color_space,
2070
+ c.kCGImageAlphaPremultipliedLast,
2071
+ );
2072
+ if (ctx == null) return failCommand("drawMarkerOnPng", "DRAW_FAILED", "failed to create bitmap context");
2073
+ defer c.CFRelease(ctx);
2074
+
2075
+ // Draw original image
2076
+ const img_rect: c.CGRect = .{
2077
+ .origin = .{ .x = 0, .y = 0 },
2078
+ .size = .{ .width = @floatFromInt(w), .height = @floatFromInt(h) },
2079
+ };
2080
+ c.CGContextDrawImage(ctx, img_rect, image);
2081
+
2082
+ // Flip Y: CGContext origin is bottom-left, marker coords are top-left
2083
+ const px = input.x;
2084
+ const py = @as(f64, @floatFromInt(h)) - input.y;
2085
+
2086
+ const pi = std.math.pi;
2087
+
2088
+ // White crosshair (background for contrast)
2089
+ c.CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 0.95);
2090
+ c.CGContextSetLineWidth(ctx, 5);
2091
+ c.CGContextSetLineCap(ctx, 1); // kCGLineCapRound
2092
+ c.CGContextMoveToPoint(ctx, px - 22, py);
2093
+ c.CGContextAddLineToPoint(ctx, px + 22, py);
2094
+ c.CGContextStrokePath(ctx);
2095
+ c.CGContextMoveToPoint(ctx, px, py - 22);
2096
+ c.CGContextAddLineToPoint(ctx, px, py + 22);
2097
+ c.CGContextStrokePath(ctx);
2098
+
2099
+ // White ring
2100
+ c.CGContextSetLineWidth(ctx, 4);
2101
+ c.CGContextAddArc(ctx, px, py, 18, 0, 2 * pi, 0);
2102
+ c.CGContextStrokePath(ctx);
2103
+
2104
+ // Red crosshair
2105
+ c.CGContextSetRGBStrokeColor(ctx, 1, 0.176, 0.176, 1); // #ff2d2d
2106
+ c.CGContextSetLineWidth(ctx, 3);
2107
+ c.CGContextSetLineCap(ctx, 1);
2108
+ c.CGContextMoveToPoint(ctx, px - 22, py);
2109
+ c.CGContextAddLineToPoint(ctx, px + 22, py);
2110
+ c.CGContextStrokePath(ctx);
2111
+ c.CGContextMoveToPoint(ctx, px, py - 22);
2112
+ c.CGContextAddLineToPoint(ctx, px, py + 22);
2113
+ c.CGContextStrokePath(ctx);
2114
+
2115
+ // Red ring
2116
+ c.CGContextSetLineWidth(ctx, 2);
2117
+ c.CGContextAddArc(ctx, px, py, 18, 0, 2 * pi, 0);
2118
+ c.CGContextStrokePath(ctx);
2119
+
2120
+ // Filled red center dot with white stroke
2121
+ c.CGContextSetRGBFillColor(ctx, 1, 0.176, 0.176, 1);
2122
+ c.CGContextAddArc(ctx, px, py, 10, 0, 2 * pi, 0);
2123
+ c.CGContextFillPath(ctx);
2124
+ c.CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1);
2125
+ c.CGContextSetLineWidth(ctx, 3);
2126
+ c.CGContextAddArc(ctx, px, py, 10, 0, 2 * pi, 0);
2127
+ c.CGContextStrokePath(ctx);
2128
+
2129
+ // Get result image and write back
2130
+ const result_image = c.CGBitmapContextCreateImage(ctx);
2131
+ if (result_image == null) return failCommand("drawMarkerOnPng", "DRAW_FAILED", "failed to create result image");
2132
+ defer c.CFRelease(result_image);
2133
+
2134
+ writeScreenshotPng(.{
2135
+ .image = result_image,
2136
+ .output_path = input.path,
2137
+ }) catch {
2138
+ return failCommand("drawMarkerOnPng", "WRITE_FAILED", "failed to write annotated PNG");
2139
+ };
2140
+
2141
+ return okCommand();
2142
+ }
2143
+
2027
2144
  fn resolveMouseButton(button: []const u8) !MouseButtonKind {
2028
2145
  if (std.ascii.eqlIgnoreCase(button, "left")) {
2029
2146
  return .left;