mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
cocoa-cb: remove pre-allocation of window, view and layer
the pre-allocation was needed because the layer allocated a opengl context async itself and we couldn't influence that. so we had to start the core after the context was actually allocated. furthermore a window, view and layer hierarchy had to be created so the layer would create a context. now, instead of relying on the layer to create a context we do this manually and re-use that context later when the layer wants to create one async itself.
This commit is contained in:
@@ -31,9 +31,9 @@ class EventsView: NSView {
|
||||
override var acceptsFirstResponder: Bool { return true }
|
||||
|
||||
|
||||
init(frame frameRect: NSRect, cocoaCB ccb: CocoaCB) {
|
||||
init(cocoaCB ccb: CocoaCB) {
|
||||
cocoaCB = ccb
|
||||
super.init(frame: frameRect)
|
||||
super.init(frame: NSMakeRect(0, 0, 960, 480))
|
||||
autoresizingMask = [.viewWidthSizable, .viewHeightSizable]
|
||||
wantsBestResolutionOpenGLSurface = true
|
||||
register(forDraggedTypes: [NSFilenamesPboardType, NSURLPboardType])
|
||||
@@ -249,6 +249,7 @@ class EventsView: NSView {
|
||||
}
|
||||
|
||||
func canHideCursor() -> Bool {
|
||||
if cocoaCB.window == nil { return false }
|
||||
return !hasMouseDown && containsMouseLocation() && window!.isKeyWindow
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,15 @@ class VideoLayer: CAOpenGLLayer {
|
||||
super.init()
|
||||
autoresizingMask = [.layerWidthSizable, .layerHeightSizable]
|
||||
backgroundColor = NSColor.black.cgColor
|
||||
contentsScale = cocoaCB.window.backingScaleFactor
|
||||
|
||||
CGLCreateContext(copyCGLPixelFormat(forDisplayMask: 0), nil, &cglContext)
|
||||
var i: GLint = 1
|
||||
CGLSetParameter(cglContext!, kCGLCPSwapInterval, &i)
|
||||
CGLSetCurrentContext(cglContext!)
|
||||
|
||||
mpv.initRender()
|
||||
mpv.setRenderUpdateCallback(updateCallback, context: self)
|
||||
mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB)
|
||||
}
|
||||
|
||||
override init(layer: Any) {
|
||||
@@ -74,12 +82,6 @@ class VideoLayer: CAOpenGLLayer {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func setUpRender() {
|
||||
mpv.initRender()
|
||||
mpv.setRenderUpdateCallback(updateCallback, context: self)
|
||||
mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB)
|
||||
}
|
||||
|
||||
override func canDraw(inCGLContext ctx: CGLContextObj,
|
||||
pixelFormat pf: CGLPixelFormatObj,
|
||||
forLayerTime t: CFTimeInterval,
|
||||
@@ -177,23 +179,15 @@ class VideoLayer: CAOpenGLLayer {
|
||||
|
||||
if err != kCGLNoError || pix == nil {
|
||||
let errS = String(cString: CGLErrorString(err))
|
||||
print("Couldn't create CGL pixel format: \(errS) (\(err.rawValue))")
|
||||
mpv.sendError("Couldn't create CGL pixel format: \(errS) (\(err.rawValue))")
|
||||
exit(1)
|
||||
}
|
||||
return pix!
|
||||
}
|
||||
|
||||
override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj {
|
||||
let ctx = super.copyCGLContext(forPixelFormat: pf)
|
||||
var i: GLint = 1
|
||||
CGLSetParameter(ctx, kCGLCPSwapInterval, &i)
|
||||
CGLSetCurrentContext(ctx)
|
||||
cglContext = ctx
|
||||
|
||||
if let app = NSApp as? Application {
|
||||
app.initMPVCore()
|
||||
}
|
||||
return ctx
|
||||
contentsScale = cocoaCB.window.backingScaleFactor
|
||||
return cglContext!
|
||||
}
|
||||
|
||||
let updateCallback: mpv_render_update_fn = { (ctx) in
|
||||
|
||||
@@ -78,28 +78,23 @@ class Window: NSWindow, NSWindowDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
convenience init(cocoaCB ccb: CocoaCB) {
|
||||
self.init(contentRect: NSMakeRect(0, 0, 960, 480),
|
||||
styleMask: [.titled, .closable, .miniaturizable, .resizable],
|
||||
backing: .buffered, defer: false, screen: NSScreen.main())
|
||||
cocoaCB = ccb
|
||||
title = "mpv"
|
||||
}
|
||||
|
||||
convenience init(contentRect: NSRect, styleMask style: NSWindowStyleMask,
|
||||
screen: NSScreen?, cocoaCB ccb: CocoaCB)
|
||||
{
|
||||
self.init(contentRect: contentRect, styleMask: style,
|
||||
convenience init(contentRect: NSRect, screen: NSScreen?, view: NSView, cocoaCB ccb: CocoaCB) {
|
||||
self.init(contentRect: contentRect,
|
||||
styleMask: [.titled, .closable, .miniaturizable, .resizable],
|
||||
backing: .buffered, defer: false, screen: screen)
|
||||
cocoaCB = ccb
|
||||
title = cocoaCB.title
|
||||
minSize = NSMakeSize(160, 90)
|
||||
collectionBehavior = .fullScreenPrimary
|
||||
delegate = self
|
||||
contentView!.addSubview(view)
|
||||
view.frame = contentView!.frame
|
||||
|
||||
unfsContentFrame = convertToScreen(contentView!.frame)
|
||||
targetScreen = screen!
|
||||
currentScreen = screen!
|
||||
unfScreen = screen!
|
||||
initTitleBar()
|
||||
|
||||
if let app = NSApp as? Application {
|
||||
app.menuBar.register(#selector(setHalfWindowSize), for: MPM_H_SIZE)
|
||||
@@ -123,14 +118,31 @@ class Window: NSWindow, NSWindowDelegate {
|
||||
titleBarEffect!.blendingMode = .withinWindow
|
||||
titleBarEffect!.autoresizingMask = [.viewWidthSizable, .viewMinYMargin]
|
||||
|
||||
setTitleBarStyle(mpv.getStringProperty("macos-title-bar-style") ?? "dark")
|
||||
setTitleBarStyle(Int(mpv.macOpts!.macos_title_bar_style))
|
||||
contentView!.addSubview(titleBarEffect!, positioned: .above, relativeTo: nil)
|
||||
|
||||
border = mpv.getBoolProperty("border")
|
||||
}
|
||||
|
||||
func setTitleBarStyle(_ style: String) {
|
||||
var effect = style
|
||||
func setTitleBarStyle(_ style: Any) {
|
||||
var effect: String
|
||||
|
||||
if style is Int {
|
||||
switch style as! Int {
|
||||
case 4:
|
||||
effect = "auto"
|
||||
case 3:
|
||||
effect = "mediumlight"
|
||||
case 2:
|
||||
effect = "light"
|
||||
case 1:
|
||||
effect = "ultradark"
|
||||
case 0: fallthrough
|
||||
default:
|
||||
effect = "dark"
|
||||
}
|
||||
} else {
|
||||
effect = style as! String
|
||||
}
|
||||
|
||||
if effect == "auto" {
|
||||
let systemStyle = UserDefaults.standard.string(forKey: "AppleInterfaceStyle")
|
||||
effect = systemStyle == nil ? "mediumlight" : "ultradark"
|
||||
@@ -339,16 +351,26 @@ class Window: NSWindow, NSWindowDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func setOnTop(_ state: Bool) {
|
||||
func setOnTop(_ state: Bool, _ ontopLevel: Any) {
|
||||
if state {
|
||||
let ontopLevel = mpv.getStringProperty("ontop-level") ?? "window"
|
||||
switch ontopLevel {
|
||||
case "window":
|
||||
level = Int(CGWindowLevelForKey(.floatingWindow))
|
||||
case "system":
|
||||
level = Int(CGWindowLevelForKey(.statusWindow))+1
|
||||
default:
|
||||
level = Int(ontopLevel)!
|
||||
if ontopLevel is Int {
|
||||
switch ontopLevel as! Int {
|
||||
case -1:
|
||||
level = Int(CGWindowLevelForKey(.floatingWindow))
|
||||
case -2:
|
||||
level = Int(CGWindowLevelForKey(.statusWindow))+1
|
||||
default:
|
||||
level = ontopLevel as! Int
|
||||
}
|
||||
} else {
|
||||
switch ontopLevel as! String {
|
||||
case "window":
|
||||
level = Int(CGWindowLevelForKey(.floatingWindow))
|
||||
case "system":
|
||||
level = Int(CGWindowLevelForKey(.statusWindow))+1
|
||||
default:
|
||||
level = Int(ontopLevel as! String)!
|
||||
}
|
||||
}
|
||||
collectionBehavior.remove(.transient)
|
||||
collectionBehavior.insert(.managed)
|
||||
|
||||
@@ -30,6 +30,10 @@ class CocoaCB: NSObject {
|
||||
var cursorVisibilityWanted: Bool = true
|
||||
var isShuttingDown: Bool = false
|
||||
|
||||
var title: String = "mpv" {
|
||||
didSet { if window != nil { window.title = title } }
|
||||
}
|
||||
|
||||
enum State {
|
||||
case uninit
|
||||
case needsInit
|
||||
@@ -47,31 +51,29 @@ class CocoaCB: NSObject {
|
||||
|
||||
let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue")
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
window = Window(cocoaCB: self)
|
||||
|
||||
view = EventsView(frame: window.contentView!.bounds, cocoaCB: self)
|
||||
window.contentView!.addSubview(view)
|
||||
|
||||
convenience init(_ mpvHandle: OpaquePointer) {
|
||||
self.init()
|
||||
mpv = MPVHelper(mpvHandle)
|
||||
layer = VideoLayer(cocoaCB: self)
|
||||
view.layer = layer
|
||||
view.wantsLayer = true
|
||||
view.layerContentsPlacement = .scaleProportionallyToFit
|
||||
}
|
||||
|
||||
func setMpvHandle(_ ctx: OpaquePointer) {
|
||||
mpv = MPVHelper(ctx)
|
||||
layer.setUpRender()
|
||||
}
|
||||
|
||||
func preinit() {
|
||||
func preinit(_ vo: UnsafeMutablePointer<vo>) {
|
||||
if backendState == .uninit {
|
||||
backendState = .needsInit
|
||||
DispatchQueue.main.async {
|
||||
self.updateICCProfile()
|
||||
|
||||
if let app = NSApp as? Application {
|
||||
let ptr = mp_get_config_group(mpv.mpctx!, vo.pointee.global,
|
||||
app.getMacOSConf())
|
||||
mpv.macOpts = UnsafeMutablePointer<macos_opts>(OpaquePointer(ptr))!.pointee
|
||||
}
|
||||
startDisplayLink()
|
||||
|
||||
view = EventsView(cocoaCB: self)
|
||||
view.layer = layer
|
||||
view.wantsLayer = true
|
||||
view.layerContentsPlacement = .scaleProportionallyToFit
|
||||
startDisplayLink(vo)
|
||||
initLightSensor()
|
||||
addDisplayReconfigureObserver()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,39 +84,37 @@ class CocoaCB: NSObject {
|
||||
|
||||
func reconfig(_ vo: UnsafeMutablePointer<vo>) {
|
||||
if backendState == .needsInit {
|
||||
initBackend(vo)
|
||||
DispatchQueue.main.sync { self.initBackend(vo) }
|
||||
} else {
|
||||
layer.setVideo(true)
|
||||
updateWindowSize(vo)
|
||||
layer.update()
|
||||
DispatchQueue.main.async {
|
||||
self.layer.setVideo(true)
|
||||
self.updateWindowSize(vo)
|
||||
self.layer.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initBackend(_ vo: UnsafeMutablePointer<vo>) {
|
||||
let opts: mp_vo_opts = vo.pointee.opts.pointee
|
||||
NSApp.setActivationPolicy(.regular)
|
||||
|
||||
let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main()
|
||||
let wr = getWindowGeometry(forScreen: targetScreen!, videoOut: vo)
|
||||
let win = Window(contentRect: wr, styleMask: window.styleMask,
|
||||
screen: targetScreen, cocoaCB: self)
|
||||
win.title = window.title
|
||||
win.setOnTop(mpv.getBoolProperty("ontop"))
|
||||
win.keepAspect = mpv.getBoolProperty("keepaspect-window")
|
||||
window.close()
|
||||
window = win
|
||||
window.contentView!.addSubview(view)
|
||||
view.frame = window.contentView!.frame
|
||||
window.initTitleBar()
|
||||
|
||||
setAppIcon()
|
||||
|
||||
let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main()
|
||||
let wr = getWindowGeometry(forScreen: targetScreen!, videoOut: vo)
|
||||
window = Window(contentRect: wr, screen: targetScreen, view: view, cocoaCB: self)
|
||||
updateICCProfile()
|
||||
window.setOnTop(Bool(opts.ontop), Int(opts.ontop_level))
|
||||
window.keepAspect = Bool(opts.keepaspect_window)
|
||||
window.title = title
|
||||
window.border = Bool(opts.border)
|
||||
|
||||
window.isRestorable = false
|
||||
window.makeMain()
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
layer.setVideo(true)
|
||||
|
||||
if mpv.getBoolProperty("fullscreen") {
|
||||
if Bool(opts.fullscreen) {
|
||||
DispatchQueue.main.async {
|
||||
self.window.toggleFullScreen(nil)
|
||||
}
|
||||
@@ -122,13 +122,12 @@ class CocoaCB: NSObject {
|
||||
window.isMovableByWindowBackground = true
|
||||
}
|
||||
|
||||
initLightSensor()
|
||||
addDisplayReconfigureObserver()
|
||||
backendState = .init
|
||||
}
|
||||
|
||||
func updateWindowSize(_ vo: UnsafeMutablePointer<vo>) {
|
||||
let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main()
|
||||
let opts: mp_vo_opts = vo.pointee.opts.pointee
|
||||
let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main()
|
||||
let wr = getWindowGeometry(forScreen: targetScreen!, videoOut: vo)
|
||||
if !window.isVisible {
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
@@ -155,8 +154,11 @@ class CocoaCB: NSObject {
|
||||
return kCVReturnSuccess
|
||||
}
|
||||
|
||||
func startDisplayLink() {
|
||||
let displayId = UInt32(window.screen!.deviceDescription["NSScreenNumber"] as! Int)
|
||||
func startDisplayLink(_ vo: UnsafeMutablePointer<vo>) {
|
||||
let opts: mp_vo_opts = vo.pointee.opts.pointee
|
||||
let screen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main()
|
||||
let displayId = screen!.deviceDescription["NSScreenNumber"] as! UInt32
|
||||
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&link)
|
||||
CVDisplayLinkSetCurrentCGDisplay(link!, displayId)
|
||||
if #available(macOS 10.12, *) {
|
||||
@@ -324,8 +326,8 @@ class CocoaCB: NSObject {
|
||||
}
|
||||
|
||||
func getTargetScreen(forFullscreen fs: Bool) -> NSScreen? {
|
||||
let screenID = fs ? mpv.getStringProperty("fs-screen") ?? "current":
|
||||
mpv.getStringProperty("screen") ?? "current"
|
||||
let screenType = fs ? "fs-screen" : "screen"
|
||||
let screenID = mpv.getStringProperty(screenType) ?? "current"
|
||||
|
||||
switch screenID {
|
||||
case "current", "default", "all":
|
||||
@@ -432,21 +434,17 @@ class CocoaCB: NSObject {
|
||||
let titleData = data!.assumingMemoryBound(to: Int8.self)
|
||||
let title = String(cString: titleData)
|
||||
DispatchQueue.main.async {
|
||||
ccb.window.title = String(cString: titleData)
|
||||
ccb.title = String(cString: titleData)
|
||||
}
|
||||
return VO_TRUE
|
||||
case VOCTRL_PREINIT:
|
||||
ccb.preinit()
|
||||
DispatchQueue.main.sync { ccb.preinit(vo!) }
|
||||
return VO_TRUE
|
||||
case VOCTRL_UNINIT:
|
||||
DispatchQueue.main.async {
|
||||
ccb.uninit()
|
||||
}
|
||||
DispatchQueue.main.async { ccb.uninit() }
|
||||
return VO_TRUE
|
||||
case VOCTRL_RECONFIG:
|
||||
DispatchQueue.main.async {
|
||||
ccb.reconfig(vo!)
|
||||
}
|
||||
ccb.reconfig(vo!)
|
||||
return VO_TRUE
|
||||
default:
|
||||
return VO_NOTIMPL
|
||||
@@ -472,7 +470,7 @@ class CocoaCB: NSObject {
|
||||
func processEvent(_ event: UnsafePointer<mpv_event>) {
|
||||
switch event.pointee.event_id {
|
||||
case MPV_EVENT_SHUTDOWN:
|
||||
if window.isAnimating {
|
||||
if window != nil && window.isAnimating {
|
||||
isShuttingDown = true
|
||||
return
|
||||
}
|
||||
@@ -499,7 +497,7 @@ class CocoaCB: NSObject {
|
||||
}
|
||||
case "ontop":
|
||||
if let data = MPVHelper.mpvFlagToBool(property.data) {
|
||||
window.setOnTop(data)
|
||||
window.setOnTop(data, mpv.getStringProperty("ontop-level") ?? "window")
|
||||
}
|
||||
case "keepaspect-window":
|
||||
if let data = MPVHelper.mpvFlagToBool(property.data) {
|
||||
|
||||
Reference in New Issue
Block a user