summaryrefslogtreecommitdiffstats
path: root/video/out/cocoa-cb/window.swift
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/cocoa-cb/window.swift')
-rw-r--r--video/out/cocoa-cb/window.swift537
1 files changed, 0 insertions, 537 deletions
diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift
deleted file mode 100644
index ce7947cb90..0000000000
--- a/video/out/cocoa-cb/window.swift
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import Cocoa
-
-class Window: NSWindow, NSWindowDelegate {
-
- weak var cocoaCB: CocoaCB! = nil
- var mpv: MPVHelper? { get { return cocoaCB.mpv } }
- var libmpv: LibmpvHelper { get { return cocoaCB.libmpv } }
-
- var targetScreen: NSScreen?
- var previousScreen: NSScreen?
- var currentScreen: NSScreen?
- var unfScreen: NSScreen?
-
- var unfsContentFrame: NSRect?
- var isInFullscreen: Bool = false
- var isAnimating: Bool = false
- var isMoving: Bool = false
- var forceTargetScreen: Bool = false
-
- var keepAspect: Bool = true {
- didSet {
- if let contentViewFrame = contentView?.frame, !isInFullscreen {
- unfsContentFrame = convertToScreen(contentViewFrame)
- }
-
- if keepAspect {
- contentAspectRatio = unfsContentFrame?.size ?? contentAspectRatio
- } else {
- resizeIncrements = NSSize(width: 1.0, height: 1.0)
- }
- }
- }
-
- var border: Bool = true {
- didSet { if !border { cocoaCB.titleBar?.hide() } }
- }
-
- override var canBecomeKey: Bool { return true }
- override var canBecomeMain: Bool { return true }
-
- override var styleMask: NSWindow.StyleMask {
- get { return super.styleMask }
- set {
- let responder = firstResponder
- let windowTitle = title
- super.styleMask = newValue
- makeFirstResponder(responder)
- title = windowTitle
- }
- }
-
- 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)
-
- // 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 let wantedScreen = screen, screen != NSScreen.main {
- var absoluteWantedOrigin = contentRect.origin
- absoluteWantedOrigin.x += wantedScreen.frame.origin.x
- absoluteWantedOrigin.y += wantedScreen.frame.origin.y
-
- if !NSEqualPoints(absoluteWantedOrigin, self.frame.origin) {
- self.setFrameOrigin(absoluteWantedOrigin)
- }
- }
-
- cocoaCB = ccb
- title = cocoaCB.title
- minSize = NSMakeSize(160, 90)
- collectionBehavior = .fullScreenPrimary
- delegate = self
-
- 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)
- 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)
- }
- }
-
- override func toggleFullScreen(_ sender: Any?) {
- if isAnimating {
- return
- }
-
- isAnimating = true
-
- targetScreen = cocoaCB.getTargetScreen(forFullscreen: !isInFullscreen)
- if targetScreen == nil && previousScreen == nil {
- targetScreen = screen
- } else if targetScreen == nil {
- targetScreen = previousScreen
- previousScreen = nil
- } else {
- previousScreen = screen
- }
-
- if let contentViewFrame = contentView?.frame, !isInFullscreen {
- unfsContentFrame = convertToScreen(contentViewFrame)
- unfScreen = screen
- }
- // move window to target screen when going to fullscreen
- if let tScreen = targetScreen, !isInFullscreen && (tScreen != screen) {
- let frame = calculateWindowPosition(for: tScreen, withoutBounds: false)
- setFrame(frame, display: true)
- }
-
- if Bool(mpv?.opts.native_fs ?? 1) {
- super.toggleFullScreen(sender)
- } else {
- if !isInFullscreen {
- setToFullScreen()
- }
- else {
- setToWindow()
- }
- }
- }
-
- func customWindowsToEnterFullScreen(for window: NSWindow) -> [NSWindow]? {
- return [window]
- }
-
- func customWindowsToExitFullScreen(for window: NSWindow) -> [NSWindow]? {
- return [window]
- }
-
- func window(_ window: NSWindow, startCustomAnimationToEnterFullScreenWithDuration duration: TimeInterval) {
- 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(tScreen.frame, display: true)
- }, completionHandler: { })
- }
-
- func window(_ window: NSWindow, startCustomAnimationToExitFullScreenWithDuration duration: TimeInterval) {
- 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)
-
- NSAnimationContext.runAnimationGroup({ (context) -> Void in
- context.duration = getFsAnimationDuration(duration - 0.05)
- window.animator().setFrame(newFrame, display: true)
- }, completionHandler: { })
- }
-
- func windowDidEnterFullScreen(_ notification: Notification) {
- isInFullscreen = true
- cocoaCB.mpv?.setConfigProperty(fullscreen: isInFullscreen)
- cocoaCB.updateCursorVisibility()
- endAnimation(frame)
- cocoaCB.titleBar?.show()
- }
-
- func windowDidExitFullScreen(_ notification: Notification) {
- guard let tScreen = targetScreen else { return }
- isInFullscreen = false
- cocoaCB.mpv?.setConfigProperty(fullscreen: isInFullscreen)
- endAnimation(calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen))
- cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit
- }
-
- func windowDidFailToEnterFullScreen(_ window: NSWindow) {
- guard let tScreen = targetScreen else { return }
- let newFrame = calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen)
- setFrame(newFrame, display: true)
- endAnimation()
- }
-
- func windowDidFailToExitFullScreen(_ window: NSWindow) {
- guard let targetFrame = targetScreen?.frame else { return }
- setFrame(targetFrame, display: true)
- endAnimation()
- cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit
- }
-
- func endAnimation(_ newFrame: NSRect = NSZeroRect) {
- if !NSEqualRects(newFrame, NSZeroRect) && isAnimating {
- NSAnimationContext.runAnimationGroup({ (context) -> Void in
- context.duration = 0.01
- self.animator().setFrame(newFrame, display: true)
- }, completionHandler: nil )
- }
-
- isAnimating = false
- cocoaCB.layer?.update()
- cocoaCB.checkShutdown()
- }
-
- func setToFullScreen() {
- guard let targetFrame = targetScreen?.frame else { return }
- styleMask.insert(.fullScreen)
- NSApp.presentationOptions = [.autoHideMenuBar, .autoHideDock]
- setFrame(targetFrame, display: true)
- endAnimation()
- isInFullscreen = true
- cocoaCB.mpv?.setConfigProperty(fullscreen: isInFullscreen)
- cocoaCB.layer?.update()
- }
-
- func setToWindow() {
- 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.mpv?.setConfigProperty(fullscreen: isInFullscreen)
- cocoaCB.layer?.update()
- }
-
- func getFsAnimationDuration(_ def: Double) -> Double {
- let duration = libmpv.macOpts.macos_fs_animation_duration
- if duration < 0 {
- return def
- } else {
- return Double(duration)/1000
- }
- }
-
- func setOnTop(_ state: Bool, _ ontopLevel: Int) {
- if state {
- switch ontopLevel {
- case -1:
- level = .floating
- case -2:
- level = .statusBar + 1
- default:
- level = NSWindow.Level(ontopLevel)
- }
- collectionBehavior.remove(.transient)
- collectionBehavior.insert(.managed)
- } else {
- level = .normal
- }
- }
-
- func setMinimized(_ stateWanted: Bool) {
- if isMiniaturized == stateWanted { return }
-
- if stateWanted {
- performMiniaturize(self)
- } else {
- deminiaturize(self)
- }
- }
-
- func setMaximized(_ stateWanted: Bool) {
- if isZoomed == stateWanted { return }
-
- zoom(self)
- }
-
- func updateMovableBackground(_ pos: NSPoint) {
- if !isInFullscreen {
- isMovableByWindowBackground = mpv?.canBeDraggedAt(pos) ?? true
- } else {
- isMovableByWindowBackground = false
- }
- }
-
- func updateFrame(_ rect: NSRect) {
- if rect != frame {
- let cRect = frameRect(forContentRect: rect)
- unfsContentFrame = rect
- setFrame(cRect, display: true)
- cocoaCB.layer?.update(force: true)
- }
- }
-
- 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
- }
- }
- }
-
- override func setFrame(_ frameRect: NSRect, display flag: Bool) {
- if frameRect.width < minSize.width || frameRect.height < minSize.height {
- mpv?.sendVerbose("tried to set too small window size: \(frameRect.size)")
- return
- }
-
- super.setFrame(frameRect, display: flag)
-
- if let size = unfsContentFrame?.size, keepAspect {
- contentAspectRatio = 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)
- }
-
- func aspectFit(rect r: NSRect, in rTarget: NSRect) -> NSRect {
- var s = rTarget.width / r.width;
- if r.height*s > rTarget.height {
- s = rTarget.height / r.height
- }
- let w = r.width * s
- let h = r.height * s
- return NSRect(x: rTarget.midX - w/2, y: rTarget.midY - h/2, width: w, height: h)
- }
-
- func calculateWindowPosition(for tScreen: NSScreen, withoutBounds: Bool) -> NSRect {
- 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 = screen.frame
- let visibleWindow = NSIntersectionRect(unfsScreenFrame, newFrame)
-
- // calculate visible area of every side
- let left = newFrame.origin.x - unfsScreenFrame.origin.x
- let right = unfsScreenFrame.size.width -
- (newFrame.origin.x - unfsScreenFrame.origin.x + newFrame.size.width)
- let bottom = newFrame.origin.y - unfsScreenFrame.origin.y
- let top = unfsScreenFrame.size.height -
- (newFrame.origin.y - unfsScreenFrame.origin.y + newFrame.size.height)
-
- // normalize visible areas, decide which one to take horizontal/vertical
- var xPer = (unfsScreenFrame.size.width - visibleWindow.size.width)
- var yPer = (unfsScreenFrame.size.height - visibleWindow.size.height)
- if xPer != 0 { xPer = (left >= 0 || right < 0 ? left : right) / xPer }
- if yPer != 0 { yPer = (bottom >= 0 || top < 0 ? bottom : top) / yPer }
-
- // calculate visible area for every side for target screen
- let xNewLeft = targetFrame.origin.x +
- (targetFrame.size.width - visibleWindow.size.width) * xPer
- let xNewRight = targetFrame.origin.x + targetFrame.size.width -
- (targetFrame.size.width - visibleWindow.size.width) * xPer - newFrame.size.width
- let yNewBottom = targetFrame.origin.y +
- (targetFrame.size.height - visibleWindow.size.height) * yPer
- let yNewTop = targetFrame.origin.y + targetFrame.size.height -
- (targetFrame.size.height - visibleWindow.size.height) * yPer - newFrame.size.height
-
- // calculate new coordinates, decide which one to take horizontal/vertical
- newFrame.origin.x = left >= 0 || right < 0 ? xNewLeft : xNewRight
- newFrame.origin.y = bottom >= 0 || top < 0 ? yNewBottom : yNewTop
-
- // don't place new window on top of a visible menubar
- let topMar = targetFrame.size.height -
- (newFrame.origin.y - targetFrame.origin.y + newFrame.size.height)
- let menuBarHeight = targetFrame.size.height -
- (targetVisibleFrame.size.height + targetVisibleFrame.origin.y)
- if topMar < menuBarHeight {
- newFrame.origin.y -= top - menuBarHeight
- }
-
- if withoutBounds {
- return newFrame
- }
-
- // screen bounds right and left
- if newFrame.origin.x + newFrame.size.width > targetFrame.origin.x + targetFrame.size.width {
- newFrame.origin.x = targetFrame.origin.x + targetFrame.size.width - newFrame.size.width
- }
- if newFrame.origin.x < targetFrame.origin.x {
- newFrame.origin.x = targetFrame.origin.x
- }
-
- // screen bounds top and bottom
- if newFrame.origin.y + newFrame.size.height > targetFrame.origin.y + targetFrame.size.height {
- newFrame.origin.y = targetFrame.origin.y + targetFrame.size.height - newFrame.size.height
- }
- if newFrame.origin.y < targetFrame.origin.y {
- newFrame.origin.y = targetFrame.origin.y
- }
- return newFrame
- }
-
- override func constrainFrameRect(_ frameRect: NSRect, to tScreen: NSScreen?) -> NSRect {
- if (isAnimating && !isInFullscreen) || (!isAnimating && isInFullscreen) {
- return frameRect
- }
-
- guard let ts: NSScreen = tScreen ?? screen ?? NSScreen.main else {
- return frameRect
- }
- var nf: NSRect = frameRect
- let of: NSRect = frame
- let vf: NSRect = (isAnimating ? (targetScreen ?? ts) : ts).visibleFrame
- let ncf: NSRect = contentRect(forFrameRect: nf)
-
- // screen bounds top and bottom
- if NSMaxY(nf) > NSMaxY(vf) {
- nf.origin.y = NSMaxY(vf) - NSHeight(nf)
- }
- if NSMaxY(ncf) < NSMinY(vf) {
- nf.origin.y = NSMinY(vf) + NSMinY(ncf) - NSMaxY(ncf)
- }
-
- // screen bounds right and left
- if NSMinX(nf) > NSMaxX(vf) {
- nf.origin.x = NSMaxX(vf) - NSWidth(nf)
- }
- if NSMaxX(nf) < NSMinX(vf) {
- nf.origin.x = NSMinX(vf)
- }
-
- if NSHeight(nf) < NSHeight(vf) && NSHeight(of) > NSHeight(vf) && !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
- }
- return nf
- }
-
- @objc func setNormalWindowSize() { setWindowScale(1.0) }
- @objc func setHalfWindowSize() { setWindowScale(0.5) }
- @objc func setDoubleWindowSize() { setWindowScale(2.0) }
-
- func setWindowScale(_ scale: Double) {
- mpv?.command("set window-scale \(scale)")
- }
-
- func addWindowScale(_ scale: Double) {
- if !isInFullscreen {
- mpv?.command("add window-scale \(scale)")
- }
- }
-
- func windowDidChangeScreen(_ notification: Notification) {
- if screen == nil {
- return
- }
- if !isAnimating && (currentScreen != screen) {
- previousScreen = screen
- }
- if currentScreen != screen {
- cocoaCB.updateDisplaylink()
- cocoaCB.layer?.update(force: true)
- }
- currentScreen = screen
- }
-
- func windowDidChangeScreenProfile(_ notification: Notification) {
- cocoaCB.layer?.needsICCUpdate = true
- }
-
- func windowDidChangeBackingProperties(_ notification: Notification) {
- cocoaCB.layer?.contentsScale = backingScaleFactor
- cocoaCB.flagEvents(VO_EVENT_DPI)
- }
-
- func windowWillStartLiveResize(_ notification: Notification) {
- cocoaCB.layer?.inLiveResize = true
- }
-
- func windowDidEndLiveResize(_ notification: Notification) {
- cocoaCB.layer?.inLiveResize = false
- cocoaCB.mpv?.setConfigProperty(maximized: isZoomed)
- }
-
- func windowShouldClose(_ sender: NSWindow) -> Bool {
- cocoa_put_key(MP_KEY_CLOSE_WIN)
- return false
- }
-
- func windowDidMiniaturize(_ notification: Notification) {
- cocoaCB.mpv?.setConfigProperty(minimized: true)
- }
-
- func windowDidDeminiaturize(_ notification: Notification) {
- cocoaCB.mpv?.setConfigProperty(minimized: false)
- }
-
- func windowDidResignKey(_ notification: Notification) {
- cocoaCB.setCursorVisiblility(true)
- }
-
- func windowDidBecomeKey(_ notification: Notification) {
- cocoaCB.updateCursorVisibility()
- }
-
- func windowDidChangeOcclusionState(_ notification: Notification) {
- if occlusionState.contains(.visible) {
- cocoaCB.layer?.update(force: true)
- cocoaCB.updateCursorVisibility()
- }
- }
-
- func windowWillMove(_ notification: Notification) {
- isMoving = true
- }
-
- func windowDidMove(_ notification: Notification) {
- cocoaCB.mpv?.setConfigProperty(maximized: isZoomed)
- }
-}