diff options
Diffstat (limited to 'video/out/mac/window.swift')
-rw-r--r-- | video/out/mac/window.swift | 152 |
1 files changed, 81 insertions, 71 deletions
diff --git a/video/out/mac/window.swift b/video/out/mac/window.swift index 8ae3a6549e..6ca5d2128d 100644 --- a/video/out/mac/window.swift +++ b/video/out/mac/window.swift @@ -19,21 +19,24 @@ import Cocoa class Window: NSWindow, NSWindowDelegate { weak var common: Common! = nil - var mpv: MPVHelper? { get { return common.mpv } } + var option: OptionHelper { return common.option } + var input: InputHelper? { return common.input } var targetScreen: NSScreen? var previousScreen: NSScreen? var currentScreen: NSScreen? var unfScreen: NSScreen? - var unfsContentFrame: NSRect? + var unfsContentFrame: NSRect = NSRect(x: 0, y: 0, width: 160, height: 90) var isInFullscreen: Bool = false - var isAnimating: Bool = false var isMoving: Bool = false var previousStyleMask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable] - var unfsContentFramePixel: NSRect { get { return convertToBacking(unfsContentFrame ?? NSRect(x: 0, y: 0, width: 160, height: 90)) } } - var framePixel: NSRect { get { return convertToBacking(frame) } } + var isAnimating: Bool = false + let animationLock: NSCondition = NSCondition() + + var unfsContentFramePixel: NSRect { return convertToBacking(unfsContentFrame) } + @objc var framePixel: NSRect { return convertToBacking(frame) } var keepAspect: Bool = true { didSet { @@ -42,7 +45,7 @@ class Window: NSWindow, NSWindowDelegate { } if keepAspect { - contentAspectRatio = unfsContentFrame?.size ?? contentAspectRatio + contentAspectRatio = unfsContentFrame.size } else { resizeIncrements = NSSize(width: 1.0, height: 1.0) } @@ -80,16 +83,18 @@ class Window: NSWindow, NSWindowDelegate { absoluteWantedOrigin.x += wantedScreen.frame.origin.x absoluteWantedOrigin.y += wantedScreen.frame.origin.y - if !NSEqualPoints(absoluteWantedOrigin, self.frame.origin) { + if absoluteWantedOrigin != self.frame.origin { self.setFrameOrigin(absoluteWantedOrigin) } } common = com title = com.title - minSize = NSMakeSize(160, 90) + minSize = NSSize(width: 160, height: 90) collectionBehavior = .fullScreenPrimary + ignoresMouseEvents = option.vo.cursor_passthrough delegate = self + unfsContentFrame = contentRect if let cView = contentView { cView.addSubview(view) @@ -101,13 +106,11 @@ class Window: NSWindow, NSWindowDelegate { currentScreen = screen unfScreen = screen - if let app = NSApp as? Application { - app.menuBar.register(#selector(setHalfWindowSize), for: MPM_H_SIZE) - app.menuBar.register(#selector(setNormalWindowSize), for: MPM_N_SIZE) - app.menuBar.register(#selector(setDoubleWindowSize), for: MPM_D_SIZE) - app.menuBar.register(#selector(performMiniaturize(_:)), for: MPM_MINIMIZE) - app.menuBar.register(#selector(performZoom(_:)), for: MPM_ZOOM) - } + AppHub.shared.menu?.register(#selector(setHalfWindowSize), key: .itemHalfSize) + AppHub.shared.menu?.register(#selector(setNormalWindowSize), key: .itemNormalSize) + AppHub.shared.menu?.register(#selector(setDoubleWindowSize), key: .itemDoubleSize) + AppHub.shared.menu?.register(#selector(performMiniaturize(_:)), key: .itemMinimize) + AppHub.shared.menu?.register(#selector(performZoom(_:)), key: .itemZoom) } override func toggleFullScreen(_ sender: Any?) { @@ -115,7 +118,9 @@ class Window: NSWindow, NSWindowDelegate { return } + animationLock.lock() isAnimating = true + animationLock.unlock() targetScreen = common.getTargetScreen(forFullscreen: !isInFullscreen) if targetScreen == nil && previousScreen == nil { @@ -137,13 +142,12 @@ class Window: NSWindow, NSWindowDelegate { setFrame(frame, display: true) } - if Bool(mpv?.opts.native_fs ?? 1) { + if Bool(option.vo.native_fs) { super.toggleFullScreen(sender) } else { if !isInFullscreen { setToFullScreen() - } - else { + } else { setToWindow() } } @@ -161,7 +165,7 @@ class Window: NSWindow, NSWindowDelegate { guard let tScreen = targetScreen else { return } common.view?.layerContentsPlacement = .scaleProportionallyToFit common.titleBar?.hide() - NSAnimationContext.runAnimationGroup({ (context) -> Void in + NSAnimationContext.runAnimationGroup({ (context) in context.duration = getFsAnimationDuration(duration - 0.05) window.animator().setFrame(tScreen.frame, display: true) }, completionHandler: nil) @@ -173,12 +177,12 @@ class Window: NSWindow, NSWindowDelegate { let intermediateFrame = aspectFit(rect: newFrame, in: currentScreen.frame) common.titleBar?.hide(0.0) - NSAnimationContext.runAnimationGroup({ (context) -> Void in + NSAnimationContext.runAnimationGroup({ (context) in context.duration = 0.0 common.view?.layerContentsPlacement = .scaleProportionallyToFill window.animator().setFrame(intermediateFrame, display: true) }, completionHandler: { - NSAnimationContext.runAnimationGroup({ (context) -> Void in + NSAnimationContext.runAnimationGroup({ (context) in context.duration = self.getFsAnimationDuration(duration - 0.05) self.styleMask.remove(.fullScreen) window.animator().setFrame(newFrame, display: true) @@ -188,7 +192,7 @@ class Window: NSWindow, NSWindowDelegate { func windowDidEnterFullScreen(_ notification: Notification) { isInFullscreen = true - mpv?.setOption(fullscreen: isInFullscreen) + option.setOption(fullscreen: isInFullscreen) common.updateCursorVisibility() endAnimation(frame) common.titleBar?.show() @@ -197,7 +201,7 @@ class Window: NSWindow, NSWindowDelegate { func windowDidExitFullScreen(_ notification: Notification) { guard let tScreen = targetScreen else { return } isInFullscreen = false - mpv?.setOption(fullscreen: isInFullscreen) + option.setOption(fullscreen: isInFullscreen) endAnimation(calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen)) common.view?.layerContentsPlacement = .scaleProportionallyToFit } @@ -216,15 +220,18 @@ class Window: NSWindow, NSWindowDelegate { common.view?.layerContentsPlacement = .scaleProportionallyToFit } - func endAnimation(_ newFrame: NSRect = NSZeroRect) { - if !NSEqualRects(newFrame, NSZeroRect) && isAnimating { - NSAnimationContext.runAnimationGroup({ (context) -> Void in + func endAnimation(_ newFrame: NSRect = NSRect.zero) { + if newFrame != NSRect.zero && isAnimating { + NSAnimationContext.runAnimationGroup({ (context) in context.duration = 0.01 self.animator().setFrame(newFrame, display: true) }, completionHandler: nil ) } + animationLock.lock() isAnimating = false + animationLock.signal() + animationLock.unlock() common.windowDidEndAnimation() } @@ -242,7 +249,7 @@ class Window: NSWindow, NSWindowDelegate { setFrame(targetFrame, display: true) endAnimation() isInFullscreen = true - mpv?.setOption(fullscreen: isInFullscreen) + option.setOption(fullscreen: isInFullscreen) common.windowSetToFullScreen() } @@ -261,12 +268,20 @@ class Window: NSWindow, NSWindowDelegate { setFrame(newFrame, display: true) endAnimation() isInFullscreen = false - mpv?.setOption(fullscreen: isInFullscreen) + option.setOption(fullscreen: isInFullscreen) common.windowSetToWindow() } + func waitForAnimation() { + animationLock.lock() + while isAnimating { + animationLock.wait() + } + animationLock.unlock() + } + func getFsAnimationDuration(_ def: Double) -> Double { - let duration = mpv?.macOpts.macos_fs_animation_duration ?? -1 + let duration = option.mac.macos_fs_animation_duration if duration < 0 { return def } else { @@ -319,7 +334,7 @@ class Window: NSWindow, NSWindowDelegate { func updateMovableBackground(_ pos: NSPoint) { if !isInFullscreen { - isMovableByWindowBackground = mpv?.canBeDraggedAt(pos) ?? true + isMovableByWindowBackground = input?.draggable(at: pos) ?? true } else { isMovableByWindowBackground = false } @@ -327,42 +342,38 @@ class Window: NSWindow, NSWindowDelegate { func updateFrame(_ rect: NSRect) { if rect != frame { - let cRect = frameRect(forContentRect: rect) unfsContentFrame = rect - setFrame(cRect, display: true) - common.windowDidUpdateFrame() + if !isInFullscreen { + let cRect = frameRect(forContentRect: rect) + setFrame(cRect, display: true) + common.windowDidUpdateFrame() + } } } func updateSize(_ size: NSSize) { if let currentSize = contentView?.frame.size, size != currentSize { let newContentFrame = centeredContentSize(for: frame, size: size) - if !isInFullscreen { - updateFrame(newContentFrame) - } else { - unfsContentFrame = newContentFrame - } + updateFrame(newContentFrame) } } override func setFrame(_ frameRect: NSRect, display flag: Bool) { if frameRect.width < minSize.width || frameRect.height < minSize.height { - common.log.sendVerbose("tried to set too small window size: \(frameRect.size)") + common.log.verbose("tried to set too small window size: \(frameRect.size)") return } super.setFrame(frameRect, display: flag) - if let size = unfsContentFrame?.size, keepAspect { - contentAspectRatio = size - } + if keepAspect { contentAspectRatio = unfsContentFrame.size } } func centeredContentSize(for rect: NSRect, size sz: NSSize) -> NSRect { let cRect = contentRect(forFrameRect: rect) let dx = (cRect.size.width - sz.width) / 2 let dy = (cRect.size.height - sz.height) / 2 - return NSInsetRect(cRect, dx, dy) + return cRect.insetBy(dx: dx, dy: dy) } func aspectFit(rect r: NSRect, in rTarget: NSRect) -> NSRect { @@ -376,14 +387,13 @@ class Window: NSWindow, NSWindowDelegate { } func calculateWindowPosition(for tScreen: NSScreen, withoutBounds: Bool) -> NSRect { - guard let contentFrame = unfsContentFrame, let screen = unfScreen else { - return frame - } - var newFrame = frameRect(forContentRect: contentFrame) + guard let screen = unfScreen else { return frame } + + var newFrame = frameRect(forContentRect: unfsContentFrame) let targetFrame = tScreen.frame let targetVisibleFrame = tScreen.visibleFrame let unfsScreenFrame = screen.frame - let visibleWindow = NSIntersectionRect(unfsScreenFrame, newFrame) + let visibleWindow = unfsScreenFrame.intersection(newFrame) // calculate visible area of every side let left = newFrame.origin.x - unfsScreenFrame.origin.x @@ -446,8 +456,7 @@ class Window: NSWindow, NSWindowDelegate { override func constrainFrameRect(_ frameRect: NSRect, to tScreen: NSScreen?) -> NSRect { if (isAnimating && !isInFullscreen) || (!isAnimating && isInFullscreen || - level == NSWindow.Level(Int(CGWindowLevelForKey(.desktopWindow)))) - { + level == NSWindow.Level(Int(CGWindowLevelForKey(.desktopWindow)))) { return frameRect } @@ -460,41 +469,41 @@ class Window: NSWindow, NSWindowDelegate { let ncf: NSRect = contentRect(forFrameRect: nf) // screen bounds top and bottom - if NSMaxY(nf) > NSMaxY(vf) { - nf.origin.y = NSMaxY(vf) - NSHeight(nf) + if nf.maxY > vf.maxY { + nf.origin.y = vf.maxY - nf.height } - if NSMaxY(ncf) < NSMinY(vf) { - nf.origin.y = NSMinY(vf) + NSMinY(ncf) - NSMaxY(ncf) + if ncf.maxY < vf.minY { + nf.origin.y = vf.minY + ncf.minY - ncf.maxY } // screen bounds right and left - if NSMinX(nf) > NSMaxX(vf) { - nf.origin.x = NSMaxX(vf) - NSWidth(nf) + if nf.minX > vf.maxX { + nf.origin.x = vf.maxX - nf.width } - if NSMaxX(nf) < NSMinX(vf) { - nf.origin.x = NSMinX(vf) + if nf.maxX < vf.minX { + nf.origin.x = vf.minX } - if NSHeight(nf) < NSHeight(vf) && NSHeight(of) > NSHeight(vf) && !isInFullscreen { + if nf.height < vf.height && of.height > vf.height && !isInFullscreen { // If the window height is smaller than the visible frame, but it was // bigger previously recenter the smaller window vertically. This is // needed to counter the 'snap to top' behaviour. - nf.origin.y = (NSHeight(vf) - NSHeight(nf)) / 2 + nf.origin.y = (vf.height - nf.height) / 2 } return nf } @objc func setNormalWindowSize() { setWindowScale(1.0) } - @objc func setHalfWindowSize() { setWindowScale(0.5) } + @objc func setHalfWindowSize() { setWindowScale(0.5) } @objc func setDoubleWindowSize() { setWindowScale(2.0) } func setWindowScale(_ scale: Double) { - mpv?.command("set window-scale \(scale)") + input?.command("set window-scale \(scale)") } func addWindowScale(_ scale: Double) { if !isInFullscreen { - mpv?.command("add window-scale \(scale)") + input?.command("add current-window-scale \(scale)") } } @@ -527,30 +536,31 @@ class Window: NSWindow, NSWindowDelegate { func windowDidEndLiveResize(_ notification: Notification) { common.windowDidEndLiveResize() - mpv?.setOption(maximized: isZoomed) + option.setOption(maximized: isZoomed) - if let contentViewFrame = contentView?.frame, - !isAnimating && !isInFullscreen - { + if let contentViewFrame = contentView?.frame, !isAnimating && !isInFullscreen { unfsContentFrame = convertToScreen(contentViewFrame) } } func windowDidResize(_ notification: Notification) { + if let contentViewFrame = contentView?.frame, !isAnimating && !isInFullscreen && !inLiveResize { + unfsContentFrame = convertToScreen(contentViewFrame) + } common.windowDidResize() } func windowShouldClose(_ sender: NSWindow) -> Bool { - cocoa_put_key(MP_KEY_CLOSE_WIN) + input?.put(key: MP_KEY_CLOSE_WIN) return false } func windowDidMiniaturize(_ notification: Notification) { - mpv?.setOption(minimized: true) + option.setOption(minimized: true) } func windowDidDeminiaturize(_ notification: Notification) { - mpv?.setOption(minimized: false) + option.setOption(minimized: false) } func windowDidResignKey(_ notification: Notification) { @@ -573,6 +583,6 @@ class Window: NSWindow, NSWindowDelegate { } func windowDidMove(_ notification: Notification) { - mpv?.setOption(maximized: isZoomed) + option.setOption(maximized: isZoomed) } } |