From d5be1e272965176cb974d41fa4f6f94ada074a04 Mon Sep 17 00:00:00 2001 From: der richter Date: Fri, 29 Mar 2019 20:36:34 +0100 Subject: 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. --- video/out/cocoa-cb/events_view.swift | 10 +-- video/out/cocoa-cb/title_bar.swift | 165 +++++++++++++++++++++++++++++++++++ video/out/cocoa-cb/window.swift | 154 +------------------------------- video/out/cocoa_cb_common.swift | 5 +- wscript_build.py | 1 + 5 files changed, 179 insertions(+), 156 deletions(-) create mode 100644 video/out/cocoa-cb/title_bar.swift diff --git a/video/out/cocoa-cb/events_view.swift b/video/out/cocoa-cb/events_view.swift index aad5360d4a..b9de12ca26 100644 --- a/video/out/cocoa-cb/events_view.swift +++ b/video/out/cocoa-cb/events_view.swift @@ -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) } diff --git a/video/out/cocoa-cb/title_bar.swift b/video/out/cocoa-cb/title_bar.swift new file mode 100644 index 0000000000..fbd4ec0776 --- /dev/null +++ b/video/out/cocoa-cb/title_bar.swift @@ -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 . + */ + +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) + } +} diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift index 26308c5563..b3ccd9d94b 100644 --- a/video/out/cocoa-cb/window.swift +++ b/video/out/cocoa-cb/window.swift @@ -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) { diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 15f419e207..cf714bfa4d 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -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 diff --git a/wscript_build.py b/wscript_build.py index e08a7fe3f4..38f704ef34 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -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" ), ] -- cgit v1.2.3