// // Copyright 2026 Aarav Ravindra Kharade // import CSystem import CWayland @_silgen_name("ark_wayland_client_init") func c_ark_wayland_client_init() -> Bool @_silgen_name("ark_wayland_client_shutdown") func c_ark_wayland_client_shutdown() @_silgen_name("ark_wayland_client_create_surface") func c_ark_wayland_client_create_surface(_ width: Int32, _ height: Int32) -> UnsafeMutablePointer? @_silgen_name("ark_wayland_client_commit") func c_ark_wayland_client_commit() /// ArkGraphics — Display Client Library /// Connects to the ArkCompositor (Wayland Server) to render UI. public class ArkGraphics { public var screenWidth: Int = 1920 public var screenHeight: Int = 1080 public var buffer: UnsafeMutablePointer? public private(set) var isConnected: Bool = false public init() { // For now, fallback to a standard 1080p resolution unless /tmp/screen_size.txt exists if let str = readFileContents("/tmp/screen_size.txt") { var w = 0 var h = 0 var parsingW = true for char in str { if char == " " { parsingW = false } else if let num = char.wholeNumberValue { if parsingW { w = w * 10 + num } else { h = h * 10 + num } } } if w > 0 && h > 0 { self.screenWidth = w self.screenHeight = h } } let maxRetries = 10 for _ in 1...maxRetries { if c_ark_wayland_client_init() { isConnected = true break } usleep(500_000) } if isConnected { buffer = c_ark_wayland_client_create_surface(Int32(screenWidth), Int32(screenHeight)) if buffer == nil { print("ArkGraphics: FATAL - Failed to create Wayland surface") } } else { print("ArkGraphics: WARNING - Failed to connect to Wayland server") } } deinit { if isConnected { c_ark_wayland_client_shutdown() } } @inline(__always) private func toTopLeftY(y: Int, h: Int) -> Int { return screenHeight - y - h } // - Rendering Commands - public func fillRectRGB(x: Int, y: Int, w: Int, h: Int, r: UInt8, g: UInt8, b: UInt8) { fillRectRGBA(x: x, y: y, w: w, h: h, r: r, g: g, b: b, a: 255) } public func fillRectRGBA(x: Int, y: Int, w: Int, h: Int, r: UInt8, g: UInt8, b: UInt8, a: UInt8) { guard let p = buffer else { return } let sy = toTopLeftY(y: y, h: h) let y0 = max(0, sy) let y1 = min(screenHeight, sy + h) let x0 = max(0, x) let x1 = min(screenWidth, x + w) for cy in y0.. 0 { p[off] = UInt8(Double(b) * fVal + Double(p[off]) * curA * (1.0 - fVal)) p[off+1] = UInt8(Double(g) * fVal + Double(p[off+1]) * curA * (1.0 - fVal)) p[off+2] = UInt8(Double(r) * fVal + Double(p[off+2]) * curA * (1.0 - fVal)) p[off+3] = UInt8(newA * 255.0) } } } } } public func fillRoundedRectRGB(x: Int, y: Int, w: Int, h: Int, r: UInt8, g: UInt8, b: UInt8, radius: Int) { fillRoundedRectRGBA(x: x, y: y, w: w, h: h, r: r, g: g, b: b, a: 255, radius: radius) } public func fillRoundedRectRGBA(x: Int, y: Int, w: Int, h: Int, r: UInt8, g: UInt8, b: UInt8, a: UInt8, radius: Int) { guard let p = buffer else { return } let sy = toTopLeftY(y: y, h: h) let y0 = max(0, sy) let y1 = min(screenHeight, sy + h) let x0 = max(0, x) let x1 = min(screenWidth, x + w) let radSq = Double(radius * radius) for cy in y0.. 0 { // Check corners let innerX0 = x + radius let innerX1 = x + w - radius let innerY0 = sy + radius let innerY1 = sy + h - radius var dx = 0 var dy = 0 if cx < innerX0 { dx = innerX0 - cx } else if cx > innerX1 { dx = cx - innerX1 } if cy < innerY0 { dy = innerY0 - cy } else if cy > innerY1 { dy = cy - innerY1 } if dx > 0 && dy > 0 { if Double(dx*dx + dy*dy) > radSq { draw = false } } } if draw { let off = rowBase + cx * 4 p[off] = b p[off+1] = g p[off+2] = r p[off+3] = a } } } } public func clear(r: UInt8, g: UInt8, b: UInt8) { guard let p = buffer else { return } let count = screenWidth * screenHeight * 4 for i in stride(from: 0, to: count, by: 4) { p[i] = b p[i+1] = g p[i+2] = r p[i+3] = 255 } } public func pan() { if isConnected { c_ark_wayland_client_commit() } } public func drawHLine(x: Int, y: Int, w: Int, r: UInt8, g: UInt8, b: UInt8) { fillRectRGB(x: x, y: y, w: w, h: 1, r: r, g: g, b: b) } public func drawVLine(x: Int, y: Int, h: Int, r: UInt8, g: UInt8, b: UInt8) { fillRectRGB(x: x, y: y, w: 1, h: h, r: r, g: g, b: b) } public func drawRectOutline(x: Int, y: Int, w: Int, h: Int, r: UInt8, g: UInt8, b: UInt8, thickness: Int = 1) { fillRectRGB(x: x, y: y, w: w, h: thickness, r: r, g: g, b: b) fillRectRGB(x: x, y: y + h - thickness, w: w, h: thickness, r: r, g: g, b: b) fillRectRGB(x: x, y: y, w: thickness, h: h, r: r, g: g, b: b) fillRectRGB(x: x + w - thickness, y: y, w: thickness, h: h, r: r, g: g, b: b) } }