summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
authorder richter <der.richter@gmx.de>2024-04-01 01:00:19 +0200
committerder richter <der.richter@gmx.de>2024-04-01 22:13:39 +0200
commit3c5149795480a15bf00c1a14045294f389e37af5 (patch)
tree167e5ab3c245911a076159c108748912b55337e3 /osdep
parentd6c621b03beef1a38e66b33507a13e329e753383 (diff)
downloadmpv-3c5149795480a15bf00c1a14045294f389e37af5.tar.bz2
mpv-3c5149795480a15bf00c1a14045294f389e37af5.tar.xz
mac/app: cleanup and optimise App launch and termination
NSApp.terminate() is not a requirement to properly shut down a cocoa App since it only calls exit() internally. though when not used the cocoa termination events won't trigger, which we don't need. this prevented us to exit with a proper exit code. rework the whole termination logic to end up at one point where we can return the exit code from the mpv_main function. Fixes #7456
Diffstat (limited to 'osdep')
-rw-r--r--osdep/mac/application.swift73
-rw-r--r--osdep/main-fn-mac.c5
2 files changed, 26 insertions, 52 deletions
diff --git a/osdep/mac/application.swift b/osdep/mac/application.swift
index 086b6eff66..c66be61647 100644
--- a/osdep/mac/application.swift
+++ b/osdep/mac/application.swift
@@ -19,6 +19,8 @@ import Cocoa
class Application: NSApplication, NSApplicationDelegate {
var appHub: AppHub { get { return AppHub.shared } }
+ var eventManager: NSAppleEventManager { get { return NSAppleEventManager.shared() } }
+ var isBundle: Bool { get { return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true" } }
var playbackThreadId: mp_thread!
var argc: Int32?
var argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>?
@@ -31,34 +33,6 @@ class Application: NSApplication, NSApplicationDelegate {
fatalError("init(coder:) has not been implemented")
}
- deinit {
- let eventManager = NSAppleEventManager.shared()
- eventManager.removeEventHandler(forEventClass: AEEventClass(kCoreEventClass), andEventID: kAEQuitApplication)
- }
-
- func initApplication(_ regular: Bool) {
- NSApp = self
- NSApp.delegate = self
-
- // Will be set to Regular from cocoa_common during UI creation so that we
- // don't create an icon when playing audio only files.
- NSApp.setActivationPolicy(regular ? .regular : .accessory)
-
- atexit_b({
- // Because activation policy has just been set to behave like a real
- // application, that policy must be reset on exit to prevent, among
- // other things, the menubar created here from remaining on screen.
- DispatchQueue.main.async { NSApp.setActivationPolicy(.prohibited) }
- })
- }
-
- func terminateApplication() {
- DispatchQueue.main.async {
- NSApp.hide(NSApp)
- NSApp.terminate(NSApp)
- }
- }
-
override func sendEvent(_ event: NSEvent) {
if modalWindow != nil || !appHub.input.processKey(event: event) {
super.sendEvent(event)
@@ -77,29 +51,36 @@ class Application: NSApplication, NSApplicationDelegate {
}
func applicationWillFinishLaunching(_ notification: Notification) {
- let eventManager = NSAppleEventManager.shared()
+ // register quit and exit events
eventManager.setEventHandler(
self,
andSelector: #selector(handleQuit(event:replyEvent:)),
forEventClass: AEEventClass(kCoreEventClass),
andEventID: kAEQuitApplication
)
+ atexit_b({
+ // clean up after exit() was called
+ DispatchQueue.main.async {
+ NSApp.hide(NSApp)
+ NSApp.setActivationPolicy(.prohibited)
+ self.eventManager.removeEventHandler(forEventClass: AEEventClass(kCoreEventClass), andEventID: kAEQuitApplication)
+ }
+ })
}
- // quit from App icon
+ // quit from App icon, external quit from NSWorkspace
@objc func handleQuit(event: NSAppleEventDescriptor?, replyEvent: NSAppleEventDescriptor?) {
+ // send quit to core, terminates mpv_main called in playbackThread,
if !appHub.input.command("quit") {
- terminateApplication()
+ appHub.log.warning("Could not properly shut down mpv")
+ exit(1)
}
}
- func bundleStartedFromFinder() -> Bool {
- return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true"
- }
-
func setupBundle() {
+ if !isBundle { return }
+
// started from finder the first argument after the binary may start with -psn_
- // remove it and all following
if CommandLine.argc > 1 && CommandLine.arguments[1].hasPrefix("-psn_") {
argc? = 1
argv?[1] = nil
@@ -113,28 +94,24 @@ class Application: NSApplication, NSApplicationDelegate {
let playbackThread: @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? = { (ptr: UnsafeMutableRawPointer) in
let application: Application = TypeHelper.bridge(ptr: ptr)
mp_thread_set_name("core/playback")
- let r: Int32 = mpv_main(application.argc ?? 1, application.argv)
- application.terminateApplication()
- // normally never reached - unless the cocoa mainloop hasn't started yet
- exit(r)
+ let exitCode: Int32 = mpv_main(application.argc ?? 1, application.argv)
+ // exit of any proper shut down
+ exit(exitCode)
}
@objc func main(_ argc: Int32, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>) -> Int {
self.argc = argc
self.argv = argv
- if bundleStartedFromFinder() {
- setupBundle()
- initApplication(true)
- } else {
- initApplication(false)
- }
-
+ NSApp = self
+ NSApp.delegate = self
+ NSApp.setActivationPolicy(isBundle ? .regular : .accessory)
+ setupBundle()
pthread_create(&playbackThreadId, nil, playbackThread, TypeHelper.bridge(obj: self))
appHub.input.wait()
NSApp.run()
- // This should never be reached: NSApp.run() blocks until the process is quit
+ // should never be reached
print("""
There was either a problem initializing Cocoa or the Runloop was stopped unexpectedly. \
Please report this issues to a developer.\n
diff --git a/osdep/main-fn-mac.c b/osdep/main-fn-mac.c
index ee2d6e3464..140610093f 100644
--- a/osdep/main-fn-mac.c
+++ b/osdep/main-fn-mac.c
@@ -1,9 +1,6 @@
#include "osdep/mac/app_bridge.h"
-// This is needed because Cocoa absolutely requires creating the NSApplication
-// singleton and running it in the "main" thread. It is apparently not
-// possible to do this on a separate thread at all. It is not known how
-// Apple managed this colossal fuckup.
+// Cocoa absolutely requires creating the NSApplication singleton and running it on the main thread.
int main(int argc, char *argv[])
{
return cocoa_main(argc, argv);