mirror of https://github.com/mpv-player/mpv
cocoa-cb: move all title bar related functionality in its own file
quite a lot of the title bar functionality and logic was within our window. since we recently added a custom title bar class to our window i decided to move all that functionality into that class and in its own file. this is also a preparation for the next commits.
This commit is contained in:
parent
9d5805fba4
commit
d5be1e2729
|
@ -135,14 +135,14 @@ class EventsView: NSView {
|
|||
if mpv.getBoolProperty("input-cursor") {
|
||||
cocoa_put_key_with_modifiers(SWIFT_KEY_MOUSE_LEAVE, 0)
|
||||
}
|
||||
cocoaCB.window.hideTitleBar()
|
||||
cocoaCB.titleBar.hide()
|
||||
}
|
||||
|
||||
override func mouseMoved(with event: NSEvent) {
|
||||
if mpv != nil && mpv.getBoolProperty("input-cursor") {
|
||||
signalMouseMovement(event)
|
||||
}
|
||||
cocoaCB.window.showTitleBar()
|
||||
cocoaCB.titleBar.show()
|
||||
}
|
||||
|
||||
override func mouseDragged(with event: NSEvent) {
|
||||
|
@ -260,7 +260,7 @@ class EventsView: NSView {
|
|||
let menuBarHeight = NSApp.mainMenu!.menuBarHeight
|
||||
|
||||
if cocoaCB.window.isInFullscreen && (menuBarHeight > 0) {
|
||||
topMargin = cocoaCB.window.titleBarHeight + 1 + menuBarHeight
|
||||
topMargin = TitleBar.height + 1 + menuBarHeight
|
||||
}
|
||||
|
||||
guard var vF = window?.screen?.frame else { return false }
|
||||
|
@ -272,8 +272,8 @@ class EventsView: NSView {
|
|||
|
||||
var clippedBounds = bounds.intersection(vFV)
|
||||
if !cocoaCB.window.isInFullscreen {
|
||||
clippedBounds.origin.y += cocoaCB.window.titleBarHeight
|
||||
clippedBounds.size.height -= cocoaCB.window.titleBarHeight
|
||||
clippedBounds.origin.y += TitleBar.height
|
||||
clippedBounds.size.height -= TitleBar.height
|
||||
}
|
||||
return clippedBounds.contains(pt)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* 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 TitleBar: NSVisualEffectView {
|
||||
|
||||
weak var cocoaCB: CocoaCB! = nil
|
||||
var mpv: MPVHelper! {
|
||||
get { return cocoaCB == nil ? nil : cocoaCB.mpv }
|
||||
}
|
||||
|
||||
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) } }
|
||||
}
|
||||
|
||||
convenience 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
|
||||
alphaValue = 0
|
||||
blendingMode = .withinWindow
|
||||
autoresizingMask = [.viewWidthSizable, .viewMinYMargin]
|
||||
systemBar.alphaValue = 0
|
||||
|
||||
window.contentView!.addSubview(self, positioned: .above, relativeTo: nil)
|
||||
window.titlebarAppearsTransparent = true
|
||||
window.styleMask.insert(.fullSizeContentView)
|
||||
setStyle(Int(mpv.macOpts!.macos_title_bar_style))
|
||||
}
|
||||
|
||||
// catch these events so they are not propagated to the underlying view
|
||||
override func mouseDown(with event: NSEvent) { }
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
if event.clickCount > 1 {
|
||||
let def = UserDefaults.standard
|
||||
var action = def.string(forKey: "AppleActionOnDoubleClick")
|
||||
|
||||
// macOS 10.10 and earlier
|
||||
if action == nil {
|
||||
action = def.bool(forKey: "AppleMiniaturizeOnDoubleClick") == true ?
|
||||
"Minimize" : "Maximize"
|
||||
}
|
||||
|
||||
if action == "Minimize" {
|
||||
cocoaCB.window.miniaturize(self)
|
||||
} else if action == "Maximize" {
|
||||
cocoaCB.window.zoom(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setStyle(_ 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"
|
||||
}
|
||||
|
||||
switch effect {
|
||||
case "mediumlight":
|
||||
cocoaCB.window.appearance = NSAppearance(named: NSAppearanceNameVibrantLight)
|
||||
material = .titlebar
|
||||
state = .followsWindowActiveState
|
||||
case "light":
|
||||
cocoaCB.window.appearance = NSAppearance(named: NSAppearanceNameVibrantLight)
|
||||
material = .light
|
||||
state = .active
|
||||
case "ultradark":
|
||||
cocoaCB.window.appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
|
||||
material = .titlebar
|
||||
state = .followsWindowActiveState
|
||||
case "dark": fallthrough
|
||||
default:
|
||||
cocoaCB.window.appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
|
||||
material = .dark
|
||||
state = .active
|
||||
}
|
||||
}
|
||||
|
||||
func show() {
|
||||
if (!cocoaCB.window.border && !cocoaCB.window.isInFullscreen) { return }
|
||||
let loc = cocoaCB.view.convert(cocoaCB.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 {
|
||||
animator().alphaValue = 1
|
||||
isHidden = false
|
||||
}
|
||||
}, completionHandler: nil )
|
||||
|
||||
if loc.y > TitleBar.height {
|
||||
hideDelayed()
|
||||
} else {
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hide), object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func hide() {
|
||||
if cocoaCB.window.isInFullscreen && !cocoaCB.window.isAnimating {
|
||||
alphaValue = 0
|
||||
isHidden = true
|
||||
return
|
||||
}
|
||||
NSAnimationContext.runAnimationGroup({ (context) -> Void in
|
||||
context.duration = 0.20
|
||||
systemBar.animator().alphaValue = 0
|
||||
animator().alphaValue = 0
|
||||
}, completionHandler: {
|
||||
self.buttons.forEach { $0.isHidden = true }
|
||||
self.isHidden = true
|
||||
})
|
||||
}
|
||||
|
||||
func hideDelayed() {
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: self,
|
||||
selector: #selector(hide),
|
||||
object: nil)
|
||||
perform(#selector(hide), with: nil, afterDelay: 0.5)
|
||||
}
|
||||
}
|
|
@ -17,31 +17,6 @@
|
|||
|
||||
import Cocoa
|
||||
|
||||
class CustomTtitleBar: NSVisualEffectView {
|
||||
|
||||
// catch these events so they are not propagated to the underlying view
|
||||
override func mouseDown(with event: NSEvent) { }
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
if event.clickCount > 1 {
|
||||
let def = UserDefaults.standard
|
||||
var action = def.string(forKey: "AppleActionOnDoubleClick")
|
||||
|
||||
// macOS 10.10 and earlier
|
||||
if action == nil {
|
||||
action = def.bool(forKey: "AppleMiniaturizeOnDoubleClick") == true ?
|
||||
"Minimize" : "Maximize"
|
||||
}
|
||||
|
||||
if action == "Minimize" {
|
||||
window!.miniaturize(self)
|
||||
} else if action == "Maximize" {
|
||||
window!.zoom(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Window: NSWindow, NSWindowDelegate {
|
||||
|
||||
weak var cocoaCB: CocoaCB! = nil
|
||||
|
@ -75,18 +50,7 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
}
|
||||
|
||||
var border: Bool = true {
|
||||
didSet { if !border { hideTitleBar() } }
|
||||
}
|
||||
|
||||
var titleBarEffect: NSVisualEffectView?
|
||||
var titleBar: NSView {
|
||||
get { return (standardWindowButton(.closeButton)?.superview)! }
|
||||
}
|
||||
var titleBarHeight: CGFloat {
|
||||
get { return NSWindow.frameRect(forContentRect: CGRect.zero, styleMask: .titled).size.height }
|
||||
}
|
||||
var titleButtons: [NSButton] {
|
||||
get { return ([.closeButton, .miniaturizeButton, .zoomButton] as [NSWindowButton]).flatMap { standardWindowButton($0) } }
|
||||
didSet { if !border { cocoaCB.titleBar.hide() } }
|
||||
}
|
||||
|
||||
override var canBecomeKey: Bool { return true }
|
||||
|
@ -132,7 +96,6 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
targetScreen = screen!
|
||||
currentScreen = screen!
|
||||
unfScreen = screen!
|
||||
initTitleBar()
|
||||
|
||||
if let app = NSApp as? Application {
|
||||
app.menuBar.register(#selector(setHalfWindowSize), for: MPM_H_SIZE)
|
||||
|
@ -143,115 +106,6 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func initTitleBar() {
|
||||
var f = contentView!.bounds
|
||||
f.origin.y = f.size.height - titleBarHeight
|
||||
f.size.height = titleBarHeight
|
||||
|
||||
styleMask.insert(.fullSizeContentView)
|
||||
titleBar.alphaValue = 0
|
||||
titlebarAppearsTransparent = true
|
||||
titleBarEffect = CustomTtitleBar(frame: f)
|
||||
titleBarEffect!.alphaValue = 0
|
||||
titleBarEffect!.blendingMode = .withinWindow
|
||||
titleBarEffect!.autoresizingMask = [.viewWidthSizable, .viewMinYMargin]
|
||||
|
||||
setTitleBarStyle(Int(mpv.macOpts!.macos_title_bar_style))
|
||||
contentView!.addSubview(titleBarEffect!, positioned: .above, relativeTo: nil)
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
switch effect {
|
||||
case "mediumlight":
|
||||
appearance = NSAppearance(named: NSAppearanceNameVibrantLight)
|
||||
titleBarEffect!.material = .titlebar
|
||||
titleBarEffect!.state = .followsWindowActiveState
|
||||
case "light":
|
||||
appearance = NSAppearance(named: NSAppearanceNameVibrantLight)
|
||||
titleBarEffect!.material = .light
|
||||
titleBarEffect!.state = .active
|
||||
case "ultradark":
|
||||
appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
|
||||
titleBarEffect!.material = .titlebar
|
||||
titleBarEffect!.state = .followsWindowActiveState
|
||||
case "dark": fallthrough
|
||||
default:
|
||||
appearance = NSAppearance(named: NSAppearanceNameVibrantDark)
|
||||
titleBarEffect!.material = .dark
|
||||
titleBarEffect!.state = .active
|
||||
}
|
||||
}
|
||||
|
||||
func showTitleBar() {
|
||||
if titleBarEffect == nil || (!border && !isInFullscreen) { return }
|
||||
let loc = cocoaCB.view.convert(mouseLocationOutsideOfEventStream, from: nil)
|
||||
|
||||
titleButtons.forEach { $0.isHidden = false }
|
||||
NSAnimationContext.runAnimationGroup({ (context) -> Void in
|
||||
context.duration = 0.20
|
||||
titleBar.animator().alphaValue = 1
|
||||
if !isInFullscreen && !isAnimating {
|
||||
titleBarEffect!.animator().alphaValue = 1
|
||||
titleBarEffect!.isHidden = false
|
||||
}
|
||||
}, completionHandler: nil )
|
||||
|
||||
if loc.y > titleBarHeight {
|
||||
hideTitleBarDelayed()
|
||||
} else {
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hideTitleBar), object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func hideTitleBar() {
|
||||
if titleBarEffect == nil { return }
|
||||
if isInFullscreen && !isAnimating {
|
||||
titleBarEffect!.alphaValue = 0
|
||||
titleBarEffect!.isHidden = true
|
||||
return
|
||||
}
|
||||
NSAnimationContext.runAnimationGroup({ (context) -> Void in
|
||||
context.duration = 0.20
|
||||
titleBar.animator().alphaValue = 0
|
||||
titleBarEffect!.animator().alphaValue = 0
|
||||
}, completionHandler: {
|
||||
self.titleButtons.forEach { $0.isHidden = true }
|
||||
self.titleBarEffect!.isHidden = true
|
||||
})
|
||||
}
|
||||
|
||||
func hideTitleBarDelayed() {
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: self,
|
||||
selector: #selector(hideTitleBar),
|
||||
object: nil)
|
||||
perform(#selector(hideTitleBar), with: nil, afterDelay: 0.5)
|
||||
}
|
||||
|
||||
override func toggleFullScreen(_ sender: Any?) {
|
||||
if isAnimating {
|
||||
return
|
||||
|
@ -301,7 +155,7 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
|
||||
func window(_ window: NSWindow, startCustomAnimationToEnterFullScreenWithDuration duration: TimeInterval) {
|
||||
cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFit
|
||||
hideTitleBar()
|
||||
cocoaCB.titleBar.hide()
|
||||
NSAnimationContext.runAnimationGroup({ (context) -> Void in
|
||||
context.duration = getFsAnimationDuration(duration - 0.05)
|
||||
window.animator().setFrame(targetScreen!.frame, display: true)
|
||||
|
@ -312,7 +166,7 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen)
|
||||
let intermediateFrame = aspectFit(rect: newFrame, in: screen!.frame)
|
||||
cocoaCB.view.layerContentsPlacement = .scaleProportionallyToFill
|
||||
hideTitleBar()
|
||||
cocoaCB.titleBar.hide()
|
||||
styleMask.remove(.fullScreen)
|
||||
setFrame(intermediateFrame, display: true)
|
||||
|
||||
|
@ -327,7 +181,7 @@ class Window: NSWindow, NSWindowDelegate {
|
|||
cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE)
|
||||
cocoaCB.updateCusorVisibility()
|
||||
endAnimation(frame)
|
||||
showTitleBar()
|
||||
cocoaCB.titleBar.show()
|
||||
}
|
||||
|
||||
func windowDidExitFullScreen(_ notification: Notification) {
|
||||
|
|
|
@ -22,6 +22,7 @@ class CocoaCB: NSObject {
|
|||
|
||||
var mpv: MPVHelper!
|
||||
var window: Window!
|
||||
var titleBar: TitleBar!
|
||||
var view: EventsView!
|
||||
var layer: VideoLayer!
|
||||
var link: CVDisplayLink?
|
||||
|
@ -101,6 +102,8 @@ class CocoaCB: NSObject {
|
|||
window.title = title
|
||||
window.border = Bool(opts.border)
|
||||
|
||||
titleBar = TitleBar(frame: wr, window: window, cocoaCB: self)
|
||||
|
||||
window.isRestorable = false
|
||||
window.makeMain()
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
|
@ -512,7 +515,7 @@ class CocoaCB: NSObject {
|
|||
}
|
||||
case "macos-title-bar-style":
|
||||
if let data = MPVHelper.mpvStringArrayToString(property.data) {
|
||||
window.setTitleBarStyle(data)
|
||||
titleBar.setStyle(data)
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
|
|
@ -168,6 +168,7 @@ def build(ctx):
|
|||
( "video/out/cocoa-cb/events_view.swift" ),
|
||||
( "video/out/cocoa-cb/video_layer.swift" ),
|
||||
( "video/out/cocoa-cb/window.swift" ),
|
||||
( "video/out/cocoa-cb/title_bar.swift" ),
|
||||
( "video/out/cocoa_cb_common.swift" ),
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue