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:
der richter 2019-03-29 20:36:34 +01:00 committed by Jan Ekström
parent 9d5805fba4
commit d5be1e2729
5 changed files with 179 additions and 156 deletions

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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" ),
]