// // SignalData.swift // Adwaita // // Created by david-swift on 31.07.24. // import CAdw /// Data to pass to signal handlers. public class SignalData { /// The closure. public var closure: ([Any?]) -> Void /// Destroy the class. public var selfDestruction: (() -> Void)? /// The closure as a C handler. var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void { { _, data in let data = unsafeBitCast(data, to: SignalData.self) data.closure([]) } } /// The closure as a C handler with three parameters. var threeParamsHandler: @convention(c) ( UnsafeMutableRawPointer, UnsafeRawPointer?, UnsafeMutableRawPointer ) -> Void { { _, arg1, data in let data = unsafeBitCast(data, to: SignalData.self) data.closure([arg1]) } } /// The closure as a C handler with four parameters. var fourParamsHandler: @convention(c) ( UnsafeMutableRawPointer, UnsafeRawPointer?, UnsafeRawPointer?, UnsafeMutableRawPointer ) -> Void { { _, arg1, arg2, data in let data = unsafeBitCast(data, to: SignalData.self) data.closure([arg1, arg2]) } } /// The closure as a C handler with five parameters. var fiveParamsHandler: @convention(c) ( UnsafeMutableRawPointer, UnsafeRawPointer?, Double, Double, UnsafeMutableRawPointer ) -> Void { { _, arg1, arg2, arg3, data in let data = unsafeBitCast(data, to: SignalData.self) data.closure([arg1, arg2, arg3]) } } /// Initialize the signal data. /// - Parameters: /// - closure: The signal's closure. /// - destroy: The self destruction. public convenience init(closure: @escaping () -> Void, destroy: (() -> Void)? = nil) { self.init(closure: { _ in closure() }, destroy: destroy) } /// Initialize the signal data. /// - Parameters: /// - closure: The signal's closure. /// - destroy: The self destruction. public init(closure: @escaping ([Any]) -> Void, destroy: (() -> Void)? = nil) { self.closure = closure self.selfDestruction = destroy } /// Connect the signal data to a signal. /// - Parameters: /// - pointer: The pointer to the object which holds the signal. /// - signal: The signal's name. /// - argCount: The number of arguments. public func connect(pointer: UnsafeMutableRawPointer?, signal: String, argCount: Int = 0) { let callback: GCallback if argCount >= 3 { callback = unsafeBitCast(fiveParamsHandler, to: GCallback.self) } else if argCount == 2 { callback = unsafeBitCast(fourParamsHandler, to: GCallback.self) } else if argCount == 1 { callback = unsafeBitCast(threeParamsHandler, to: GCallback.self) } else { callback = unsafeBitCast(handler, to: GCallback.self) } let destroy: GClosureNotify = { data, _ in guard let data else { return } let signalData: SignalData = Unmanaged.fromOpaque(data).takeUnretainedValue() signalData.selfDestruction?() } g_signal_connect_data( pointer, signal, callback, Unmanaged.passUnretained(self).toOpaque().cast(), destroy, G_CONNECT_AFTER ) } }