diff options
-rw-r--r-- | DOCS/man/options.rst | 12 | ||||
-rw-r--r-- | options/options.c | 5 | ||||
-rw-r--r-- | options/options.h | 1 | ||||
-rw-r--r-- | osdep/macOS_mpv_helper.swift | 1 | ||||
-rw-r--r-- | osdep/macosx_application.m | 16 | ||||
-rw-r--r-- | video/out/cocoa-cb/events_view.swift | 11 | ||||
-rw-r--r-- | video/out/cocoa-cb/window.swift | 118 | ||||
-rw-r--r-- | video/out/cocoa_cb_common.swift | 8 | ||||
-rw-r--r-- | waftools/detections/compiler_swift.py | 6 |
9 files changed, 158 insertions, 20 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 1a5af8121a..2a2ca665c3 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -4852,6 +4852,18 @@ The following video options are currently all specific to ``--vo=gpu`` and OS X only. +``--macos-title-bar-style=<dark|ultradark|light|mediumlight|auto>`` + Sets the styling of the title bar (default: dark). + OS X and cocoa-cb only + + :dark: Dark title bar with vibrancy, a subtle blurring effect that + dynamically blends the background (Video) into the title bar. + :ultradark: Darker title bar with vibrancy (like QuickTime Player). + :light: Bright title bar with vibrancy. + :mediumlight: Less bright title bar with vibrancy. + :auto: Detects the system settings and sets the title bar styling + appropriately, either ultradark or mediumlight. + ``--android-surface-size=<WxH>`` Set dimensions of the rendering surface used by the Android gpu context. Needs to be set by the embedding application if the dimensions change during diff --git a/options/options.c b/options/options.c index 2f4116299d..878f7be12f 100644 --- a/options/options.c +++ b/options/options.c @@ -87,6 +87,7 @@ extern const struct m_sub_options d3d11_conf; extern const struct m_sub_options d3d11va_conf; extern const struct m_sub_options angle_conf; extern const struct m_sub_options cocoa_conf; +extern const struct m_sub_options macos_conf; extern const struct m_sub_options android_conf; static const struct m_sub_options screenshot_conf = { @@ -735,6 +736,10 @@ const m_option_t mp_opts[] = { OPT_SUBSTRUCT("", cocoa_opts, cocoa_conf, 0), #endif +#if HAVE_MACOS_COCOA_CB + OPT_SUBSTRUCT("", macos_opts, macos_conf, 0), +#endif + #if HAVE_ANDROID OPT_SUBSTRUCT("", android_opts, android_conf, 0), #endif diff --git a/options/options.h b/options/options.h index db5b92b86a..e76aa03db4 100644 --- a/options/options.h +++ b/options/options.h @@ -341,6 +341,7 @@ typedef struct MPOpts { struct d3d11_opts *d3d11_opts; struct d3d11va_opts *d3d11va_opts; struct cocoa_opts *cocoa_opts; + struct macos_opts *macos_opts; struct android_opts *android_opts; struct dvd_opts *dvd_opts; diff --git a/osdep/macOS_mpv_helper.swift b/osdep/macOS_mpv_helper.swift index 15081d0133..c8b9771ba6 100644 --- a/osdep/macOS_mpv_helper.swift +++ b/osdep/macOS_mpv_helper.swift @@ -39,6 +39,7 @@ class MPVHelper: NSObject { mpv_observe_property(mpvHandle, 0, "ontop", MPV_FORMAT_FLAG) mpv_observe_property(mpvHandle, 0, "border", MPV_FORMAT_FLAG) mpv_observe_property(mpvHandle, 0, "keepaspect-window", MPV_FORMAT_FLAG) + mpv_observe_property(mpvHandle, 0, "macos-title-bar-style", MPV_FORMAT_STRING) } func setGLCB() { diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m index a65910ec9e..fe117f7a1c 100644 --- a/osdep/macosx_application.m +++ b/osdep/macosx_application.m @@ -23,6 +23,7 @@ #include "common/msg.h" #include "input/input.h" #include "player/client.h" +#include "options/m_config.h" #import "osdep/macosx_application_objc.h" #include "osdep/macosx_compat.h" @@ -39,6 +40,21 @@ #define MPV_PROTOCOL @"mpv://" +struct macos_opts { + int macos_title_bar_style; +}; + +#define OPT_BASE_STRUCT struct macos_opts +const struct m_sub_options macos_conf = { + .opts = (const struct m_option[]) { + OPT_CHOICE("macos-title-bar-style", macos_title_bar_style, 0, + ({"dark", 0}, {"ultradark", 1}, {"light", 2}, + {"mediumlight", 3}, {"auto", 4})), + {0} + }, + .size = sizeof(struct macos_opts), +}; + // Whether the NSApplication singleton was created. If this is false, we are // running in libmpv mode, and cocoa_main() was never called. static bool application_instantiated; diff --git a/video/out/cocoa-cb/events_view.swift b/video/out/cocoa-cb/events_view.swift index 4cb154c64a..e2da8345f1 100644 --- a/video/out/cocoa-cb/events_view.swift +++ b/video/out/cocoa-cb/events_view.swift @@ -110,12 +110,14 @@ class EventsView: NSView { if mpv.getBoolProperty("input-cursor") { cocoa_put_key_with_modifiers(SWIFT_KEY_MOUSE_LEAVE, 0) } + cocoaCB.window.hideTitleBar() } override func mouseMoved(with event: NSEvent) { if mpv != nil && mpv.getBoolProperty("input-cursor") { signalMouseMovement(event) } + cocoaCB.window.showTitleBar() } override func mouseDragged(with event: NSEvent) { @@ -233,8 +235,7 @@ class EventsView: NSView { let menuBarHeight = NSApp.mainMenu!.menuBarHeight if cocoaCB.window.isInFullscreen && (menuBarHeight > 0) { - let titleBar = NSWindow.frameRect(forContentRect: CGRect.zero, styleMask: .titled) - topMargin = titleBar.size.height + 1 + menuBarHeight + topMargin = cocoaCB.window.titleBarHeight + 1 + menuBarHeight } var vF = window!.screen!.frame @@ -244,7 +245,11 @@ class EventsView: NSView { let vFV = convert(vFW, from: nil) let pt = convert(window!.mouseLocationOutsideOfEventStream, from: nil) - let clippedBounds = bounds.intersection(vFV) + var clippedBounds = bounds.intersection(vFV) + if !cocoaCB.window.isInFullscreen { + clippedBounds.origin.y += cocoaCB.window.titleBarHeight + clippedBounds.size.height -= cocoaCB.window.titleBarHeight + } return clippedBounds.contains(pt) } diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift index 869bfb8be6..bd94330dcb 100644 --- a/video/out/cocoa-cb/window.swift +++ b/video/out/cocoa-cb/window.swift @@ -49,6 +49,21 @@ 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 [NSWindow.ButtonType]).flatMap { standardWindowButton($0) } } + } + override var canBecomeKey: Bool { return true } override var canBecomeMain: Bool { return true } @@ -95,6 +110,94 @@ 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 = NSVisualEffectView(frame: f) + titleBarEffect!.alphaValue = 0 + titleBarEffect!.blendingMode = .withinWindow + titleBarEffect!.autoresizingMask = [.viewWidthSizable, .viewMinYMargin] + + setTitleBarStyle(mpv.getStringProperty("macos-title-bar-style") ?? "dark") + contentView!.addSubview(titleBarEffect!, positioned: .above, relativeTo: nil) + + border = mpv.getBoolProperty("border") + } + + func setTitleBarStyle(_ style: String) { + var effect = style + 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 !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 + } + }, completionHandler: nil ) + + if loc.y > titleBarHeight { + hideTitleBarDelayed() + } else { + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(hideTitleBar), object: nil) + } + } + + func hideTitleBar() { + if isInFullscreen && !isAnimating { + titleBarEffect!.alphaValue = 0 + 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 } + }) + } + + 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 @@ -146,6 +249,7 @@ class Window: NSWindow, NSWindowDelegate { let cRect = contentRect(forFrameRect: frame) var intermediateFrame = aspectFit(rect: cRect, in: targetScreen!.frame) intermediateFrame = frameRect(forContentRect: intermediateFrame) + hideTitleBar() NSAnimationContext.runAnimationGroup({ (context) -> Void in context.duration = duration - 0.05 @@ -156,6 +260,7 @@ class Window: NSWindow, NSWindowDelegate { func window(_ window: NSWindow, startCustomAnimationToExitFullScreenWithDuration duration: TimeInterval) { let newFrame = calculateWindowPosition(for: targetScreen!, withoutBounds: targetScreen == screen) let intermediateFrame = aspectFit(rect: newFrame, in: screen!.frame) + hideTitleBar() setFrame(intermediateFrame, display: true) NSAnimationContext.runAnimationGroup({ (context) -> Void in @@ -169,6 +274,7 @@ class Window: NSWindow, NSWindowDelegate { cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) cocoaCB.updateCusorVisibility() endAnimation(frame) + showTitleBar() } func windowDidExitFullScreen(_ notification: Notification) { @@ -222,18 +328,6 @@ class Window: NSWindow, NSWindowDelegate { cocoaCB.layer.neededFlips += 1 } - func setBorder(_ state: Bool) { - if styleMask.contains(.titled) != state { - if state { - styleMask.remove(.borderless) - styleMask.insert(.titled) - } else { - styleMask.remove(.titled) - styleMask.insert(.borderless) - } - } - } - func setOnTop(_ state: Bool) { if state { let ontopLevel = mpv.getStringProperty("ontop-level") ?? "window" diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index cd43195a3e..c18bb29971 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -99,12 +99,12 @@ class CocoaCB: NSObject { screen: targetScreen, cocoaCB: self) win.title = window.title win.setOnTop(mpv.getBoolProperty("ontop")) - win.setBorder(mpv.getBoolProperty("border")) win.keepAspect = mpv.getBoolProperty("keepaspect-window") window.close() window = win window.contentView!.addSubview(view) view.frame = window.contentView!.frame + window.initTitleBar() setAppIcon() window.isRestorable = false @@ -486,7 +486,7 @@ class CocoaCB: NSObject { switch String(cString: property.name) { case "border": if let data = MPVHelper.mpvFlagToBool(property.data) { - window.setBorder(data) + window.border = data } case "ontop": if let data = MPVHelper.mpvFlagToBool(property.data) { @@ -496,6 +496,10 @@ class CocoaCB: NSObject { if let data = MPVHelper.mpvFlagToBool(property.data) { window.keepAspect = data } + case "macos-title-bar-style": + if let data = MPVHelper.mpvStringArrayToString(property.data) { + window.setTitleBarStyle(data) + } default: break } diff --git a/waftools/detections/compiler_swift.py b/waftools/detections/compiler_swift.py index 81c71415f7..2e24362ecf 100644 --- a/waftools/detections/compiler_swift.py +++ b/waftools/detections/compiler_swift.py @@ -8,8 +8,9 @@ def __run(cmd): return "" def __add_swift_flags(ctx): - ctx.env.SWIFT_FLAGS = ('-frontend -c -sdk %s -enable-objc-interop -emit-objc-header' - ' -emit-module -parse-as-library') % (ctx.env.MACOS_SDK) + ctx.env.SWIFT_FLAGS = ('-frontend -c -sdk %s -enable-objc-interop' + ' -emit-objc-header -parse-as-library' + ' -target x86_64-apple-macosx10.10') % (ctx.env.MACOS_SDK) swift_version = __run([ctx.env.SWIFT, '-version']).split(' ')[3].split('.')[:2] major, minor = [int(n) for n in swift_version] @@ -31,7 +32,6 @@ def __find_swift_library(ctx): 'Toolchains/XcodeDefault.xctoolchain/usr/lib/swift_static/macosx', 'usr/lib/swift_static/macosx' ] - dev_path = __run('xcode-select -p')[1:] dev_path = __run(['xcode-select', '-p'])[1:] ctx.start_msg('Checking for Swift Library') |