summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/out/cocoa-cb/events_view.swift40
-rw-r--r--video/out/cocoa-cb/title_bar.swift62
-rw-r--r--video/out/cocoa-cb/video_layer.swift207
-rw-r--r--video/out/cocoa-cb/window.swift128
-rw-r--r--video/out/cocoa_cb_common.swift283
5 files changed, 411 insertions, 309 deletions
diff --git a/video/out/cocoa-cb/events_view.swift b/video/out/cocoa-cb/events_view.swift
index b9de12ca26..9c30e32ca0 100644
--- a/video/out/cocoa-cb/events_view.swift
+++ b/video/out/cocoa-cb/events_view.swift
@@ -20,9 +20,7 @@ import Cocoa
class EventsView: NSView {
weak var cocoaCB: CocoaCB!
- var mpv: MPVHelper! {
- get { return cocoaCB == nil ? nil : cocoaCB.mpv }
- }
+ var mpv: MPVHelper { get { return cocoaCB.mpv } }
var tracker: NSTrackingArea?
var hasMouseDown: Bool = false
@@ -46,13 +44,14 @@ class EventsView: NSView {
}
override func updateTrackingAreas() {
- if tracker != nil {
- removeTrackingArea(tracker!)
+ if let tracker = self.tracker {
+ removeTrackingArea(tracker)
}
tracker = NSTrackingArea(rect: bounds,
options: [.activeAlways, .mouseEnteredAndExited, .mouseMoved, .enabledDuringMouseDrag],
owner: self, userInfo: nil)
+ // here tracker is guaranteed to be none-nil
addTrackingArea(tracker!)
if containsMouseLocation() {
@@ -72,6 +71,7 @@ class EventsView: NSView {
}
func isURL(_ str: String) -> Bool {
+ // force unwrapping is fine here, regex is guarnteed to be valid
let regex = try! NSRegularExpression(pattern: "^(https?|ftp)://[^\\s/$.?#].[^\\s]*$",
options: .caseInsensitive)
let isURL = regex.numberOfMatches(in: str,
@@ -135,14 +135,14 @@ class EventsView: NSView {
if mpv.getBoolProperty("input-cursor") {
cocoa_put_key_with_modifiers(SWIFT_KEY_MOUSE_LEAVE, 0)
}
- cocoaCB.titleBar.hide()
+ cocoaCB.titleBar?.hide()
}
override func mouseMoved(with event: NSEvent) {
- if mpv != nil && mpv.getBoolProperty("input-cursor") {
+ if mpv.getBoolProperty("input-cursor") {
signalMouseMovement(event)
}
- cocoaCB.titleBar.show()
+ cocoaCB.titleBar?.show()
}
override func mouseDragged(with event: NSEvent) {
@@ -161,7 +161,7 @@ class EventsView: NSView {
if mpv.getBoolProperty("input-cursor") {
signalMouseUp(event)
}
- cocoaCB.window.isMoving = false
+ cocoaCB.window?.isMoving = false
}
override func rightMouseDown(with event: NSEvent) {
@@ -210,8 +210,8 @@ class EventsView: NSView {
point = convertToBacking(point)
point.y = -point.y
- cocoaCB.window.updateMovableBackground(point)
- if !cocoaCB.window.isMoving {
+ cocoaCB.window?.updateMovableBackground(point)
+ if !(cocoaCB.window?.isMoving ?? false) {
mpv.setMousePosition(point)
}
}
@@ -257,21 +257,23 @@ class EventsView: NSView {
func containsMouseLocation() -> Bool {
if cocoaCB == nil { return false }
var topMargin: CGFloat = 0.0
- let menuBarHeight = NSApp.mainMenu!.menuBarHeight
+ let menuBarHeight = NSApp.mainMenu?.menuBarHeight ?? 23.0
+
+ guard let window = cocoaCB.window else { return false }
+ guard var vF = window.screen?.frame else { return false }
- if cocoaCB.window.isInFullscreen && (menuBarHeight > 0) {
+ if window.isInFullscreen && (menuBarHeight > 0) {
topMargin = TitleBar.height + 1 + menuBarHeight
}
- guard var vF = window?.screen?.frame else { return false }
vF.size.height -= topMargin
- let vFW = window!.convertFromScreen(vF)
+ let vFW = window.convertFromScreen(vF)
let vFV = convert(vFW, from: nil)
- let pt = convert(window!.mouseLocationOutsideOfEventStream, from: nil)
+ let pt = convert(window.mouseLocationOutsideOfEventStream, from: nil)
var clippedBounds = bounds.intersection(vFV)
- if !cocoaCB.window.isInFullscreen {
+ if !window.isInFullscreen {
clippedBounds.origin.y += TitleBar.height
clippedBounds.size.height -= TitleBar.height
}
@@ -279,8 +281,8 @@ class EventsView: NSView {
}
func canHideCursor() -> Bool {
- if cocoaCB.window == nil { return false }
- return !hasMouseDown && containsMouseLocation() && window!.isKeyWindow
+ guard let window = cocoaCB.window else { return false }
+ return !hasMouseDown && containsMouseLocation() && window.isKeyWindow
}
func getMpvButton(_ event: NSEvent) -> Int32 {
diff --git a/video/out/cocoa-cb/title_bar.swift b/video/out/cocoa-cb/title_bar.swift
index 8a7bf30f02..596a13ba7b 100644
--- a/video/out/cocoa-cb/title_bar.swift
+++ b/video/out/cocoa-cb/title_bar.swift
@@ -19,19 +19,17 @@ import Cocoa
class TitleBar: NSVisualEffectView {
- weak var cocoaCB: CocoaCB! = nil
- var mpv: MPVHelper! {
- get { return cocoaCB == nil ? nil : cocoaCB.mpv }
- }
+ weak var cocoaCB: CocoaCB!
+ var mpv: MPVHelper { get { return cocoaCB.mpv } }
- var systemBar: NSView {
- get { return (cocoaCB.window.standardWindowButton(.closeButton)?.superview)! }
+ var systemBar: NSView? {
+ get { return cocoaCB.window?.standardWindowButton(.closeButton)?.superview }
}
static var height: CGFloat {
get { return NSWindow.frameRect(forContentRect: CGRect.zero, styleMask: .titled).size.height }
}
var buttons: [NSButton] {
- get { return ([.closeButton, .miniaturizeButton, .zoomButton] as [NSWindowButton]).flatMap { cocoaCB.window.standardWindowButton($0) } }
+ get { return ([.closeButton, .miniaturizeButton, .zoomButton] as [NSWindowButton]).flatMap { cocoaCB.window?.standardWindowButton($0) } }
}
override var material: NSVisualEffectView.Material {
@@ -52,24 +50,28 @@ class TitleBar: NSVisualEffectView {
}
}
- convenience init(frame: NSRect, window: NSWindow, cocoaCB ccb: CocoaCB) {
+ init(frame: NSRect, window: NSWindow, cocoaCB ccb: CocoaCB) {
let f = NSMakeRect(0, frame.size.height - TitleBar.height,
frame.size.width, TitleBar.height)
- self.init(frame: f)
cocoaCB = ccb
+ super.init(frame: f)
alphaValue = 0
blendingMode = .withinWindow
autoresizingMask = [.viewWidthSizable, .viewMinYMargin]
- systemBar.alphaValue = 0
+ systemBar?.alphaValue = 0
state = .followsWindowActiveState
wantsLayer = true
- window.contentView!.addSubview(self, positioned: .above, relativeTo: nil)
+ window.contentView?.addSubview(self, positioned: .above, relativeTo: nil)
window.titlebarAppearsTransparent = true
window.styleMask.insert(.fullSizeContentView)
- set(appearance: Int(mpv.macOpts!.macos_title_bar_appearance))
- set(material: Int(mpv.macOpts!.macos_title_bar_material))
- set(color: mpv.macOpts!.macos_title_bar_color)
+ set(appearance: Int(mpv.macOpts?.macos_title_bar_appearance ?? 0))
+ set(material: Int(mpv.macOpts?.macos_title_bar_material ?? 0))
+ set(color: mpv.macOpts?.macos_title_bar_color ?? "#00000000")
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
}
// catch these events so they are not propagated to the underlying view
@@ -87,34 +89,34 @@ class TitleBar: NSVisualEffectView {
}
if action == "Minimize" {
- cocoaCB.window.miniaturize(self)
+ window?.miniaturize(self)
} else if action == "Maximize" {
- cocoaCB.window.zoom(self)
+ window?.zoom(self)
}
}
}
func set(appearance: Any) {
if appearance is Int {
- window!.appearance = appearanceFrom(string: String(appearance as! Int))
+ window?.appearance = appearanceFrom(string: String(appearance as? Int ?? 0))
} else {
- window!.appearance = appearanceFrom(string: appearance as! String)
+ window?.appearance = appearanceFrom(string: appearance as? String ?? "auto")
}
}
func set(material: Any) {
if material is Int {
- self.material = materialFrom(string: String(material as! Int))
+ self.material = materialFrom(string: String(material as? Int ?? 0))
} else {
- self.material = materialFrom(string: material as! String)
+ self.material = materialFrom(string: material as? String ?? "titlebar")
}
}
func set(color: Any) {
if color is String {
- layer?.backgroundColor = NSColor(hex: color as! String).cgColor
+ layer?.backgroundColor = NSColor(hex: color as? String ?? "#00000000").cgColor
} else {
- let col = color as! m_color
+ let col = color as? m_color ?? m_color(r: 0, g: 0, b: 0, a: 0)
let red = CGFloat(col.r)/255
let green = CGFloat(col.g)/255
let blue = CGFloat(col.b)/255
@@ -125,20 +127,21 @@ class TitleBar: NSVisualEffectView {
}
func show() {
- if (!cocoaCB.window.border && !cocoaCB.window.isInFullscreen) { return }
- let loc = cocoaCB.view.convert(cocoaCB.window.mouseLocationOutsideOfEventStream, from: nil)
+ guard let window = cocoaCB.window else { return }
+ if !window.border && !window.isInFullscreen { return }
+ let loc = cocoaCB.view?.convert(window.mouseLocationOutsideOfEventStream, from: nil)
buttons.forEach { $0.isHidden = false }
NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = 0.20
- systemBar.animator().alphaValue = 1
- if !cocoaCB.window.isInFullscreen && !cocoaCB.window.isAnimating {
+ systemBar?.animator().alphaValue = 1
+ if !window.isInFullscreen && !window.isAnimating {
animator().alphaValue = 1
isHidden = false
}
}, completionHandler: nil )
- if loc.y > TitleBar.height {
+ if loc?.y ?? 0 > TitleBar.height {
hideDelayed()
} else {
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hide), object: nil)
@@ -146,14 +149,15 @@ class TitleBar: NSVisualEffectView {
}
func hide() {
- if cocoaCB.window.isInFullscreen && !cocoaCB.window.isAnimating {
+ guard let window = cocoaCB.window else { return }
+ if window.isInFullscreen && !window.isAnimating {
alphaValue = 0
isHidden = true
return
}
NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = 0.20
- systemBar.animator().alphaValue = 0
+ systemBar?.animator().alphaValue = 0
animator().alphaValue = 0
}, completionHandler: {
self.buttons.forEach { $0.isHidden = true }
diff --git a/video/out/cocoa-cb/video_layer.swift b/video/out/cocoa-cb/video_layer.swift
index 5de57b9e00..895d9faf29 100644
--- a/video/out/cocoa-cb/video_layer.swift
+++ b/video/out/cocoa-cb/video_layer.swift
@@ -19,63 +19,61 @@ import Cocoa
import OpenGL.GL
import OpenGL.GL3
+let glVersions: [CGLOpenGLProfile] = [
+ kCGLOGLPVersion_3_2_Core,
+ kCGLOGLPVersion_Legacy
+]
+
+let glFormatBase: [CGLPixelFormatAttribute] = [
+ kCGLPFAOpenGLProfile,
+ kCGLPFAAccelerated,
+ kCGLPFADoubleBuffer
+]
+
+let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [
+ kCGLPFAOpenGLProfile,
+ kCGLPFARendererID,
+ CGLPixelFormatAttribute(UInt32(kCGLRendererGenericFloatID)),
+ kCGLPFADoubleBuffer
+]
+
+let glFormatOptional: [CGLPixelFormatAttribute] = [
+ kCGLPFABackingStore,
+ kCGLPFAAllowOfflineRenderers,
+ kCGLPFASupportsAutomaticGraphicsSwitching
+]
+
+let attributeLookUp: [UInt32:String] = [
+ kCGLOGLPVersion_3_2_Core.rawValue: "kCGLOGLPVersion_3_2_Core",
+ kCGLOGLPVersion_Legacy.rawValue: "kCGLOGLPVersion_Legacy",
+ kCGLPFAOpenGLProfile.rawValue: "kCGLPFAOpenGLProfile",
+ UInt32(kCGLRendererGenericFloatID): "kCGLRendererGenericFloatID",
+ kCGLPFARendererID.rawValue: "kCGLPFARendererID",
+ kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated",
+ kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer",
+ kCGLPFABackingStore.rawValue: "kCGLPFABackingStore",
+ kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers",
+ kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching",
+]
+
class VideoLayer: CAOpenGLLayer {
weak var cocoaCB: CocoaCB!
- var mpv: MPVHelper! {
- get { return cocoaCB == nil ? nil : cocoaCB.mpv }
- }
+ var mpv: MPVHelper { get { return cocoaCB.mpv } }
let videoLock = NSLock()
let displayLock = NSLock()
+ let cglContext: CGLContextObj
+ let cglPixelFormat: CGLPixelFormatObj
var needsFlip: Bool = false
var forceDraw: Bool = false
- var cglContext: CGLContextObj? = nil
- var cglPixelFormat: CGLPixelFormatObj? = nil
- var surfaceSize: NSSize?
+ var surfaceSize: NSSize = NSSize(width: 0, height: 0)
enum Draw: Int { case normal = 1, atomic, atomicEnd }
var draw: Draw = .normal
let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue.draw")
- let glVersions: [CGLOpenGLProfile] = [
- kCGLOGLPVersion_3_2_Core,
- kCGLOGLPVersion_Legacy
- ]
-
- let glFormatBase: [CGLPixelFormatAttribute] = [
- kCGLPFAOpenGLProfile,
- kCGLPFAAccelerated,
- kCGLPFADoubleBuffer
- ]
-
- let glFormatSoftwareBase: [CGLPixelFormatAttribute] = [
- kCGLPFAOpenGLProfile,
- kCGLPFARendererID,
- CGLPixelFormatAttribute(UInt32(kCGLRendererGenericFloatID)),
- kCGLPFADoubleBuffer
- ]
-
- let glFormatOptional: [CGLPixelFormatAttribute] = [
- kCGLPFABackingStore,
- kCGLPFAAllowOfflineRenderers,
- kCGLPFASupportsAutomaticGraphicsSwitching
- ]
-
- let attributeLookUp: [UInt32:String] = [
- kCGLOGLPVersion_3_2_Core.rawValue: "kCGLOGLPVersion_3_2_Core",
- kCGLOGLPVersion_Legacy.rawValue: "kCGLOGLPVersion_Legacy",
- kCGLPFAOpenGLProfile.rawValue: "kCGLPFAOpenGLProfile",
- UInt32(kCGLRendererGenericFloatID): "kCGLRendererGenericFloatID",
- kCGLPFARendererID.rawValue: "kCGLPFARendererID",
- kCGLPFAAccelerated.rawValue: "kCGLPFAAccelerated",
- kCGLPFADoubleBuffer.rawValue: "kCGLPFADoubleBuffer",
- kCGLPFABackingStore.rawValue: "kCGLPFABackingStore",
- kCGLPFAAllowOfflineRenderers.rawValue: "kCGLPFAAllowOfflineRenderers",
- kCGLPFASupportsAutomaticGraphicsSwitching.rawValue: "kCGLPFASupportsAutomaticGraphicsSwitching",
- ]
-
var needsICCUpdate: Bool = false {
didSet {
if needsICCUpdate == true {
@@ -95,24 +93,30 @@ class VideoLayer: CAOpenGLLayer {
init(cocoaCB ccb: CocoaCB) {
cocoaCB = ccb
+ cglPixelFormat = VideoLayer.createPixelFormat(ccb.mpv)
+ cglContext = VideoLayer.createContext(ccb.mpv, cglPixelFormat)
super.init()
autoresizingMask = [.layerWidthSizable, .layerHeightSizable]
backgroundColor = NSColor.black.cgColor
- cglPixelFormat = copyCGLPixelFormat(forDisplayMask: 0)
- CGLCreateContext(cglPixelFormat!, nil, &cglContext)
var i: GLint = 1
- CGLSetParameter(cglContext!, kCGLCPSwapInterval, &i)
- CGLSetCurrentContext(cglContext!)
+ CGLSetParameter(cglContext, kCGLCPSwapInterval, &i)
+ CGLSetCurrentContext(cglContext)
mpv.initRender()
mpv.setRenderUpdateCallback(updateCallback, context: self)
mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB)
}
+ //necessary for when the layer containing window changes the screen
override init(layer: Any) {
- let oldLayer = layer as! VideoLayer
+ guard let oldLayer = layer as? VideoLayer else {
+ fatalError("init(layer: Any) passed an invalid layer")
+ }
cocoaCB = oldLayer.cocoaCB
+ surfaceSize = oldLayer.surfaceSize
+ cglPixelFormat = oldLayer.cglPixelFormat
+ cglContext = oldLayer.cglContext
super.init()
}
@@ -127,7 +131,7 @@ class VideoLayer: CAOpenGLLayer {
if inLiveResize == false {
isAsynchronous = false
}
- return mpv != nil && cocoaCB.backendState == .initialized &&
+ return cocoaCB.backendState == .initialized &&
(forceDraw || mpv.isRenderUpdateFrame())
}
@@ -147,7 +151,7 @@ class VideoLayer: CAOpenGLLayer {
}
updateSurfaceSize()
- mpv.drawRender(surfaceSize!, ctx)
+ mpv.drawRender(surfaceSize, ctx)
if needsICCUpdate {
needsICCUpdate = false
@@ -158,12 +162,12 @@ class VideoLayer: CAOpenGLLayer {
func updateSurfaceSize() {
var dims: [GLint] = [0, 0, 0, 0]
glGetIntegerv(GLenum(GL_VIEWPORT), &dims)
- surfaceSize = NSMakeSize(CGFloat(dims[2]), CGFloat(dims[3]))
+ surfaceSize = NSSize(width: CGFloat(dims[2]), height: CGFloat(dims[3]))
- if NSEqualSizes(surfaceSize!, NSZeroSize) {
+ if NSEqualSizes(surfaceSize, NSZeroSize) {
surfaceSize = bounds.size
- surfaceSize!.width *= contentsScale
- surfaceSize!.height *= contentsScale
+ surfaceSize.width *= contentsScale
+ surfaceSize.height *= contentsScale
}
}
@@ -182,28 +186,65 @@ class VideoLayer: CAOpenGLLayer {
}
override func copyCGLPixelFormat(forDisplayMask mask: UInt32) -> CGLPixelFormatObj {
- if cglPixelFormat != nil { return cglPixelFormat! }
+ return cglPixelFormat
+ }
+
+ override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj {
+ contentsScale = cocoaCB.window?.backingScaleFactor ?? 1.0
+ return cglContext
+ }
+
+ let updateCallback: mpv_render_update_fn = { (ctx) in
+ let layer: VideoLayer = unsafeBitCast(ctx, to: VideoLayer.self)
+ layer.update()
+ }
+
+ override func display() {
+ displayLock.lock()
+ let isUpdate = needsFlip
+ super.display()
+ CATransaction.flush()
+ if isUpdate && needsFlip {
+ CGLSetCurrentContext(cglContext)
+ if mpv.isRenderUpdateFrame() {
+ mpv.drawRender(NSZeroSize, cglContext, skip: true)
+ }
+ }
+ displayLock.unlock()
+ }
+
+ func update(force: Bool = false) {
+ if force { forceDraw = true }
+ queue.async {
+ if self.forceDraw || !self.inLiveResize {
+ self.needsFlip = true
+ self.display()
+ }
+ }
+ }
+ class func createPixelFormat(_ mpv: MPVHelper) -> CGLPixelFormatObj {
var pix: CGLPixelFormatObj?
var err: CGLError = CGLError(rawValue: 0)
+ let swRender = mpv.macOpts?.cocoa_cb_sw_renderer ?? -1
- if mpv.macOpts!.cocoa_cb_sw_renderer != 1 {
- (pix, err) = createPixelFormat()
+ if swRender != 1 {
+ (pix, err) = VideoLayer.findPixelFormat(mpv)
}
- if (err != kCGLNoError || pix == nil) && mpv.macOpts!.cocoa_cb_sw_renderer != 0 {
- (pix, err) = createPixelFormat(software: true)
+ if (err != kCGLNoError || pix == nil) && swRender != 0 {
+ (pix, err) = VideoLayer.findPixelFormat(mpv, software: true)
}
- if err != kCGLNoError || pix == nil {
+ guard let pixelFormat = pix, err == kCGLNoError else {
mpv.sendError("Couldn't create any CGL pixel format")
exit(1)
}
- return pix!
+ return pixelFormat
}
- func createPixelFormat(software: Bool = false) -> (CGLPixelFormatObj?, CGLError) {
+ class func findPixelFormat(_ mpv: MPVHelper, software: Bool = false) -> (CGLPixelFormatObj?, CGLError) {
var pix: CGLPixelFormatObj?
var err: CGLError = CGLError(rawValue: 0)
var npix: GLint = 0
@@ -221,7 +262,7 @@ class VideoLayer: CAOpenGLLayer {
glFormat.remove(at: index)
} else {
let attArray = glFormat.map({ (value: _CGLPixelFormatAttribute) -> String in
- return attributeLookUp[value.rawValue]!
+ return attributeLookUp[value.rawValue] ?? "unknown attribute"
})
mpv.sendVerbose("Created CGL pixel format with attributes: " +
@@ -236,45 +277,23 @@ class VideoLayer: CAOpenGLLayer {
"\(software ? "software" : "hardware accelerated") " +
"CGL pixel format: \(errS) (\(err.rawValue))")
- if software == false && mpv.macOpts!.cocoa_cb_sw_renderer == -1 {
+ if software == false && (mpv.macOpts?.cocoa_cb_sw_renderer ?? -1) == -1 {
mpv.sendWarning("Falling back to software renderer")
}
return (pix, err)
}
- override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj {
- contentsScale = cocoaCB.window.backingScaleFactor
- return cglContext!
- }
+ class func createContext(_ mpv: MPVHelper, _ pixelFormat: CGLPixelFormatObj) -> CGLContextObj {
+ var context: CGLContextObj?
+ let error = CGLCreateContext(pixelFormat, nil, &context)
- let updateCallback: mpv_render_update_fn = { (ctx) in
- let layer: VideoLayer = MPVHelper.bridge(ptr: ctx!)
- layer.update()
- }
-
- override func display() {
- displayLock.lock()
- let isUpdate = needsFlip
- super.display()
- CATransaction.flush()
- if isUpdate && needsFlip {
- CGLSetCurrentContext(cglContext!)
- if mpv.isRenderUpdateFrame() {
- mpv.drawRender(NSZeroSize, cglContext!, skip: true)
- }
+ guard let cglContext = context, error == kCGLNoError else {
+ let errS = String(cString: CGLErrorString(error))
+ mpv.sendError("Couldn't create a CGLContext: " + errS)
+ exit(1)
}
- displayLock.unlock()
- }
- func update(force: Bool = false) {
- if force { forceDraw = true }
- queue.async {
- if self.forceDraw || !self.inLiveResize {
- self.needsFlip = true
- self.display()
- }
- }
+ return cglContext
}
-
}
diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift
index b3ccd9d94b..35d9b1bd91 100644
--- a/video/out/cocoa-cb/window.swift
+++ b/video/out/cocoa-cb/window.swift
@@ -20,9 +20,7 @@ import Cocoa
class Window: NSWindow, NSWindowDelegate {
weak var cocoaCB: CocoaCB! = nil
- var mpv: MPVHelper! {
- get { return cocoaCB == nil ? nil : cocoaCB.mpv }
- }
+ var mpv: MPVHelper { get { return cocoaCB.mpv } }
var targetScreen: NSScreen?
var previousScreen: NSScreen?
@@ -37,12 +35,12 @@ class Window: NSWindow, NSWindowDelegate {
var keepAspect: Bool = true {
didSet {
- if !isInFullscreen {
- unfsContentFrame = convertToScreen(contentView!.frame)
+ if let contentViewFrame = contentView?.frame, !isInFullscreen {
+ unfsContentFrame = convertToScreen(contentViewFrame)
}
if keepAspect {
- contentAspectRatio = unfsContentFrame!.size
+ contentAspectRatio = unfsContentFrame?.size ?? contentAspectRatio
} else {
resizeIncrements = NSSize(width: 1.0, height: 1.0)
}
@@ -50,7 +48,7 @@ class Window: NSWindow, NSWindowDelegate {
}
var border: Bool = true {
- didSet { if !border { cocoaCB.titleBar.hide() } }
+ didSet { if !border { cocoaCB.titleBar?.hide() } }
}
override var canBecomeKey: Bool { return true }
@@ -74,10 +72,10 @@ class Window: NSWindow, NSWindowDelegate {
// workaround for an AppKit bug where the NSWindow can't be placed on a
// none Main screen NSScreen outside the Main screen's frame bounds
- if screen != NSScreen.main() {
+ if let wantedScreen = screen, screen != NSScreen.main() {
var absoluteWantedOrigin = contentRect.origin
- absoluteWantedOrigin.x += screen!.frame.origin.x
- absoluteWantedOrigin.y += screen!.frame.origin.y
+ absoluteWantedOrigin.x += wantedScreen.frame.origin.x
+ absoluteWantedOrigin.y += wantedScreen.frame.origin.y
if !NSEqualPoints(absoluteWantedOrigin, self.frame.origin) {
self.setFrameOrigin(absoluteWantedOrigin)
@@ -89,13 +87,16 @@ class Window: NSWindow, NSWindowDelegate {
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!
+ if let cView = contentView {
+ cView.addSubview(view)
+ view.frame = cView.frame
+ unfsContentFrame = convertToScreen(cView.frame)
+ }
+
+ targetScreen = screen
+ currentScreen = screen
+ unfScreen = screen
if let app = NSApp as? Application {
app.menuBar.register(#selector(setHalfWindowSize), for: MPM_H_SIZE)
@@ -123,13 +124,13 @@ class Window: NSWindow, NSWindowDelegate {
previousScreen = screen
}
- if !isInFullscreen {
- unfsContentFrame = convertToScreen(contentView!.frame)
+ if let contentViewFrame = contentView?.frame, !isInFullscreen {
+ unfsContentFrame = convertToScreen(contentViewFrame)
unfScreen = screen
}
// move window to target screen when going to fullscreen
- if !isInFullscreen && (targetScreen != screen) {
- let frame = calculateWindowPosition(for: targetScreen!, withoutBounds: false)
+ if let tScreen = targetScreen, !isInFullscreen && (tScreen != screen) {
+ let frame = calculateWindowPosition(for: tScreen, withoutBounds: false)
setFrame(frame, display: true)
}
@@ -154,19 +155,21 @@ class Window: NSWindow, NSWindowDelegate {
}
func window(_ window: NSWindow, startCustomAnimationToEnterFullScreenWithDuration duration: TimeInterval) {
- cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
- cocoaCB.titleBar.hide()
+ guard let tScreen = targetScreen else { return }
+ cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit
+ cocoaCB.titleBar?.hide()
NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = getFsAnimationDuration(duration - 0.05)
- window.animator().setFrame(targetScreen!.frame, display: true)
+ window.animator().setFrame(tScreen.frame, display: true)
}, completionHandler: { })
}
func window(_ window: NSWindow, startCustomAnimationToExitFullScreenWithDuration duration: TimeInterval) {
- let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)
- let intermediateFrame = aspectFit(rect: newFrame, in: screen!.frame)
- cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFill
- cocoaCB.titleBar.hide()
+ guard let tScreen = targetScreen, let currentScreen = screen else { return }
+ let newFrame = calculateWindowPosition(for: tScreen, withoutBounds: tScreen == screen)
+ let intermediateFrame = aspectFit(rect: newFrame, in: currentScreen.frame)
+ cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFill
+ cocoaCB.titleBar?.hide()
styleMask.remove(.fullScreen)
setFrame(intermediateFrame, display: true)
@@ -181,27 +184,29 @@ class Window: NSWindow, NSWindowDelegate {
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
cocoaCB.updateCusorVisibility()
endAnimation(frame)
- cocoaCB.titleBar.show()
+ cocoaCB.titleBar?.show()
}
func windowDidExitFullScreen(_ notification: Notification) {
+ guard let tScreen = targetScreen else { return }
isInFullscreen = false
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
- endAnimation(calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen))
- cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
+ endAnimation(calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen))
+ cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit
}
func windowDidFailToEnterFullScreen(_ window: NSWindow) {
- let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)
+ guard let tScreen = targetScreen else { return }
+ let newFrame = calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen)
setFrame(newFrame, display: true)
endAnimation()
}
func windowDidFailToExitFullScreen(_ window: NSWindow) {
- let newFrame = targetScreen!.frame
- setFrame(newFrame, display: true)
+ guard let targetFrame = targetScreen?.frame else { return }
+ setFrame(targetFrame, display: true)
endAnimation()
- cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
+ cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit
}
func endAnimation(_ newFrame: NSRect = NSZeroRect) {
@@ -213,29 +218,31 @@ class Window: NSWindow, NSWindowDelegate {
}
isAnimating = false
- cocoaCB.layer.update()
+ cocoaCB.layer?.update()
cocoaCB.checkShutdown()
}
func setToFullScreen() {
+ guard let targetFrame = targetScreen?.frame else { return }
styleMask.insert(.fullScreen)
NSApp.presentationOptions = [.autoHideMenuBar, .autoHideDock]
- setFrame(targetScreen!.frame, display: true)
+ setFrame(targetFrame, display: true)
endAnimation()
isInFullscreen = true
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
- cocoaCB.layer.update()
+ cocoaCB.layer?.update()
}
func setToWindow() {
- let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)
+ guard let tScreen = targetScreen else { return }
+ let newFrame = calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen)
NSApp.presentationOptions = []
setFrame(newFrame, display: true)
styleMask.remove(.fullScreen)
endAnimation()
isInFullscreen = false
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
- cocoaCB.layer.update()
+ cocoaCB.layer?.update()
}
func getFsAnimationDuration(_ def: Double) -> Double{
@@ -243,35 +250,37 @@ class Window: NSWindow, NSWindowDelegate {
if duration == "default" {
return def
} else {
- return Double(duration)!/1000
+ return (Double(duration) ?? 0.2)/1000
}
}
func setOnTop(_ state: Bool, _ ontopLevel: Any) {
+ let stdLevel = Int(CGWindowLevelForKey(.normalWindow))
+
if state {
if ontopLevel is Int {
- switch ontopLevel as! Int {
+ switch ontopLevel as? Int {
case -1:
level = Int(CGWindowLevelForKey(.floatingWindow))
case -2:
level = Int(CGWindowLevelForKey(.statusWindow))+1
default:
- level = ontopLevel as! Int
+ level = ontopLevel as? Int ?? stdLevel
}
} else {
- switch ontopLevel as! String {
+ switch ontopLevel as? String {
case "window":
level = Int(CGWindowLevelForKey(.floatingWindow))
case "system":
level = Int(CGWindowLevelForKey(.statusWindow))+1
default:
- level = Int(ontopLevel as! String)!
+ level = Int(ontopLevel as? String ?? "") ?? stdLevel
}
}
collectionBehavior.remove(.transient)
collectionBehavior.insert(.managed)
} else {
- level = Int(CGWindowLevelForKey(.normalWindow))
+ level = stdLevel
}
}
@@ -292,7 +301,7 @@ class Window: NSWindow, NSWindowDelegate {
}
func updateSize(_ size: NSSize) {
- if size != contentView!.frame.size {
+ if let currentSize = contentView?.frame.size, size != currentSize {
let newContentFrame = centeredContentSize(for: frame, size: size)
if !isInFullscreen {
updateFrame(newContentFrame)
@@ -305,8 +314,8 @@ class Window: NSWindow, NSWindowDelegate {
override func setFrame(_ frameRect: NSRect, display flag: Bool) {
super.setFrame(frameRect, display: flag)
- if keepAspect {
- contentAspectRatio = unfsContentFrame!.size
+ if let size = unfsContentFrame?.size, keepAspect {
+ contentAspectRatio = size
}
}
@@ -328,10 +337,13 @@ class Window: NSWindow, NSWindowDelegate {
}
func calculateWindowPosition(for tScreen: NSScreen, withoutBounds: Bool) -> NSRect {
- var newFrame = frameRect(forContentRect: unfsContentFrame!)
+ guard let contentFrame = unfsContentFrame, let screen = unfScreen else {
+ return frame
+ }
+ var newFrame = frameRect(forContentRect: contentFrame)
let targetFrame = tScreen.frame
let targetVisibleFrame = tScreen.visibleFrame
- let unfsScreenFrame = unfScreen!.frame
+ let unfsScreenFrame = screen.frame
let visibleWindow = NSIntersectionRect(unfsScreenFrame, newFrame)
// calculate visible area of every side
@@ -398,10 +410,12 @@ class Window: NSWindow, NSWindowDelegate {
return frameRect
}
+ guard let ts: NSScreen = tScreen ?? screen ?? NSScreen.main() else {
+ return frameRect
+ }
var nf: NSRect = frameRect
- let ts: NSScreen = tScreen ?? screen ?? NSScreen.main()!
let of: NSRect = frame
- let vf: NSRect = (isAnimating ? targetScreen! : ts).visibleFrame
+ let vf: NSRect = (isAnimating ? (targetScreen ?? ts) : ts).visibleFrame
let ncf: NSRect = contentRect(forFrameRect: nf)
// screen bounds top and bottom
@@ -451,19 +465,19 @@ class Window: NSWindow, NSWindowDelegate {
}
func windowDidChangeScreenProfile(_ notification: Notification) {
- cocoaCB.layer.needsICCUpdate = true
+ cocoaCB.layer?.needsICCUpdate = true
}
func windowDidChangeBackingProperties(_ notification: Notification) {
- cocoaCB.layer.contentsScale = backingScaleFactor
+ cocoaCB.layer?.contentsScale = backingScaleFactor
}
func windowWillStartLiveResize(_ notification: Notification) {
- cocoaCB.layer.inLiveResize = true