1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
import Cocoa
import Metal
import mlx_window
import mlx_image
func _mlx_bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer? {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
func _mlx_bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
public class MlxMain {
public var winList = [MlxWin]()
public var imgList = [MlxImg]()
var myMlxApp:NSApplication?
public var device:MTLDevice!
var loopHook:UnsafeMutableRawPointer?
var loopParam:UnsafeMutableRawPointer
var loopHookTimer:CFRunLoopTimer?
public var inLoop = false
public init(_ flag:Int = 0)
{
/// make app with top menubar
myMlxApp = NSApplication.shared
if (flag == 1)
{
NSApp.setActivationPolicy(NSApplication.ActivationPolicy.prohibited) /// for non clickable win, no top menu
}
else
{
NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular)
}
device = MTLCreateSystemDefaultDevice()!
loopParam = UnsafeMutableRawPointer(&inLoop) /// dummy addr init
/// Add observer anyway to flush pixels every loop. If loop_hook exists, call it.
var ocontext = CFRunLoopObserverContext(version:0, info:_mlx_bridge(obj:self), retain:nil, release:nil, copyDescription:nil)
let observer = CFRunLoopObserverCreate(kCFAllocatorDefault, CFRunLoopActivity.beforeWaiting.rawValue, true, 0, createOCallback(), &ocontext)
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, CFRunLoopMode.commonModes)
}
public func addWinToList(_ win:MlxWin)
{ winList.append(win) }
public func addImgToList(_ img:MlxImg)
{ imgList.append(img) }
func doCallLoopHook()
{
/// if (loopHook != nil)
/// {
_ = (unsafeBitCast(loopHook!,to:(@convention(c)(UnsafeRawPointer)->Void).self))(loopParam)
/// }
}
func createOCallback() -> CFRunLoopObserverCallBack
{
return { (cfRunloopObserver, cfrunloopactivity, info) -> Void in
let mlx:MlxMain = _mlx_bridge(ptr:info!)
mlx.winList.forEach { $0.flushImages() }
/// mlx.doCallLoopHook()
}
}
func createTCallback() -> CFRunLoopTimerCallBack
{
return { (cfRunloopTimer, info) -> Void in
let mlx:MlxMain = _mlx_bridge(ptr:info!)
mlx.doCallLoopHook()
}
}
public func addLoopHook(_ f:UnsafeMutableRawPointer?, _ p:UnsafeMutableRawPointer)
{
var tcontext = CFRunLoopTimerContext(version:0, info:_mlx_bridge(obj:self), retain:nil, release:nil, copyDescription:nil)
if (loopHook != nil)
{
CFRunLoopTimerInvalidate(loopHookTimer)
}
loopHook = f
loopParam = p
if (loopHook != nil)
{
loopHookTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0.0, 0.0001, 0, 0, createTCallback(), &tcontext)
CFRunLoopAddTimer(CFRunLoopGetMain(), loopHookTimer, CFRunLoopMode.commonModes)
}
}
}
|