import Cocoa import mlx_window import mlx_image import mlx_init func _mlx_bridge(obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque()) } func _mlx_bridge_retained(obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque()) } func _mlx_bridge(ptr : UnsafeRawPointer) -> T { return Unmanaged.fromOpaque(ptr).takeUnretainedValue() } func _mlx_bridge_transfer(ptr : UnsafeRawPointer) -> T { return Unmanaged.fromOpaque(ptr).takeRetainedValue() } let MLX_SYNC_IMAGE_WRITABLE = Int32(1) let MLX_SYNC_WIN_FLUSH_CMD = Int32(2) let MLX_SYNC_WIN_CMD_COMPLETED = Int32(3) /// C decl @_cdecl("mlx_init") public func mlx_init_swift() -> UnsafeRawPointer { let mm = MlxMain() return (_mlx_bridge_retained(obj:mm)) } @_cdecl("mlx_loop") public func mlx_loop_swift(_ mlxptr:UnsafeRawPointer) { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.inLoop = true NSApp.run() } @_cdecl("mlx_new_window") public func mlx_new_window_swift(_ mlxptr:UnsafeRawPointer, Width w:UInt32, Height h:UInt32, Title t:UnsafePointer) -> UnsafeRawPointer { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) let mw = MlxWin(device: mlx.device, width: Int(w), height: Int(h), title: String(cString: t)) mw.setNotifs() mw.initMetal() mlx.addWinToList(mw) return (_mlx_bridge_retained(obj:mw)) } @_cdecl("mlx_key_hook") public func mlx_key_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 3, fct: fctptr, param: paramptr) return (Int32(0)); } @_cdecl("mlx_mouse_hook") public func mlx_mouse_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 4, fct: fctptr, param: paramptr) return (Int32(0)); } @_cdecl("mlx_hook") public func mlx_hook_swift(_ winptr:UnsafeRawPointer, _ xevent:Int32, _ xmask:Int32, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: Int(xevent), fct: fctptr, param: paramptr) return (Int32(0)); } @_cdecl("mlx_expose_hook") public func mlx_expose_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 12, fct: fctptr, param: paramptr) return (Int32(0)); } @_cdecl("mlx_loop_hook") public func mlx_loop_hook_swift(_ mlxptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.addLoopHook(fctptr, paramptr) return (Int32(0)); } @_cdecl("mlx_do_key_autorepeatoff") public func mlx_do_key_autorepeatoff_swift(_ mlxptr:UnsafeRawPointer) { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.winList.forEach{ $0.setKeyRepeat(0) } } @_cdecl("mlx_do_key_autorepeaton") public func mlx_do_key_autorepeatoon_swift(_ mlxptr:UnsafeRawPointer) { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.winList.forEach{ $0.setKeyRepeat(1) } } @_cdecl("mlx_clear_window") public func mlx_clear_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer) { let win:MlxWin = _mlx_bridge(ptr:winptr) win.clearWin() } @_cdecl("mlx_pixel_put") public func mlx_pixel_put_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer, _ x:Int32, _ y:Int32, _ color:UInt32) { let win:MlxWin = _mlx_bridge(ptr:winptr) win.pixelPut(x, y, color) } @_cdecl("mlx_get_color_value") public func mlx_get_color_value(_ mlxptr:UnsafeRawPointer, _ color:UInt32) -> UInt32 { return color } @_cdecl("mlx_new_image") public func mlx_new_image(_ mlxptr:UnsafeRawPointer, _ width:Int32, _ height:Int32) -> UnsafeRawPointer { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) let img = MlxImg(d:mlx.device, w:Int(width), h:Int(height)) mlx.addImgToList(img) /// print(CFGetRetainCount(img)) return (_mlx_bridge_retained(obj:img)) } @_cdecl("mlx_get_data_addr") public func mlx_get_data_addr_swift(_ imgptr:UnsafeRawPointer, _ bpp:UnsafeMutablePointer, _ sizeline:UnsafeMutablePointer, _ endian:UnsafeMutablePointer) -> UnsafeMutablePointer { let img:MlxImg = _mlx_bridge(ptr:imgptr) bpp.pointee = 32 sizeline.pointee = Int32(img.texture_sizeline) endian.pointee = Int32(0) return img.texture_data } @_cdecl("mlx_put_image_to_window") public func mlx_put_image_to_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer, _ imgptr:UnsafeRawPointer, _ x:Int32, _ y:Int32) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) let img:MlxImg = _mlx_bridge(ptr:imgptr) win.putImage(image:img, x:x, y:y) return Int32(0) } @_cdecl("mlx_put_image_to_window_scale") public func mlx_put_image_to_window_scale_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer, _ imgptr:UnsafeRawPointer, _ sx:Int32, _ sy:Int32, _ sw:Int32, _ sh:Int32, _ dx:Int32, _ dy:Int32, _ dw:Int32, _ dh:Int32, _ color:UInt32) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) let img:MlxImg = _mlx_bridge(ptr:imgptr) win.putImageScale(image:img, sx:sx, sy:sy, sw:sw, sh:sh, dx:dx, dy:dy, dw:dw, dh:dh, c:color) return Int32(0) } @_cdecl("mlx_do_sync") public func mlx_do_sync_swift(_ mlxptr:UnsafeRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.winList.forEach { $0.flushImages() } mlx.winList.forEach { $0.waitForGPU() } return Int32(0) } @_cdecl("mlx_sync") public func mlx_sync_swift(_ what:Int32, _ param:UnsafeRawPointer) -> Int32 { switch what { case MLX_SYNC_IMAGE_WRITABLE: let img:MlxImg = _mlx_bridge(ptr:param); while img.onGPU > 0 {} case MLX_SYNC_WIN_FLUSH_CMD: let win:MlxWin = _mlx_bridge(ptr:param); win.flushImages() case MLX_SYNC_WIN_CMD_COMPLETED: let win:MlxWin = _mlx_bridge(ptr:param); win.flushImages(); win.waitForGPU() default: break } return Int32(0) } @_cdecl("mlx_destroy_window") public func mlx_destroy_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) /// bridge_transfer to get the retain, at end of this func should release the MlxWin object, because no ref anymore. let win:MlxWin = _mlx_bridge_transfer(ptr:winptr) win.delNotifs() win.flushImages() win.waitForGPU() win.destroyWinE() mlx.winList.removeAll(where: { $0 === win} ) return Int32(0) } @_cdecl("mlx_destroy_image") public func mlx_destroy_image_swift(_ mlxptr:UnsafeRawPointer, _ imgptr:UnsafeRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) /// bridge_transfer to get the retain, at end of this func should release the MlxImg object, because no ref anymore. let img:MlxImg = _mlx_bridge_transfer(ptr:imgptr) mlx.winList.forEach { $0.flushImages() } while img.onGPU > 0 {} mlx.imgList.removeAll(where: { $0 === img} ) return Int32(0) } @_cdecl("mlx_get_screen_size") public func mlx_get_screen_size_swift(_ mlxptr:UnsafeRawPointer, _ sizex:UnsafeMutablePointer, _ sizey:UnsafeMutablePointer) -> Int32 { /// let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) sizex.pointee = Int32(NSScreen.main!.frame.size.width) sizey.pointee = Int32(NSScreen.main!.frame.size.height) return Int32(0) } @_cdecl("mlx_mouse_hide") public func mlx_mouse_hide_swift() -> Int32 { NSCursor.hide() return Int32(0) } @_cdecl("mlx_mouse_show") public func mlx_mouse_show_swift() -> Int32 { NSCursor.unhide() return Int32(0) } @_cdecl("mlx_mouse_move") public func mlx_mouse_move_swift(_ winptr:UnsafeRawPointer, _ x:Int32, _ y:Int32) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) let frame = win.getWinEFrame() /// let sframe = win.getScreenFrame() var pt = CGPoint() pt.x = frame.origin.x + CGFloat(x) /// pt.y = sframe.size.y - frame.size.y - frame.origin.y + 1 + y pt.y = frame.origin.y + frame.size.height - 1.0 - CGFloat(y) CGWarpMouseCursorPosition(pt) CGAssociateMouseAndMouseCursorPosition(UInt32(1)) return Int32(0); } @_cdecl("mlx_mouse_get_pos") public func mlx_mouse_get_pos_swift(_ winptr:UnsafeRawPointer, _ x:UnsafeMutablePointer, _ y:UnsafeMutablePointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) let frame = win.getWinEFrame() let point = win.getMouseLoc() x.pointee = Int32(point.x) y.pointee = Int32(frame.size.height - 1.0 - point.y) return Int32(0) }