From 8c9bbbe38978ad1057dfc1cc629476daef99e115 Mon Sep 17 00:00:00 2001 From: koekeishiya Date: Thu, 28 May 2020 16:54:38 +0200 Subject: [PATCH] #543 resolve issue with lifetime of NSRunningApplication --- CHANGELOG.md | 1 + src/process_manager.c | 2 ++ src/process_manager.h | 1 + src/workspace.h | 2 ++ src/workspace.m | 43 +++++++++++++++++++++---------------------- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6fdd6d1..2dac4dc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed - Blacklist loginwindow and ScreenSaverEngine processes [#537](https://github.com/koekeishiya/yabai/issues/537) +- Resolve some issues with the lifetime of NSRunningApplication [#543](https://github.com/koekeishiya/yabai/issues/543) ## [3.0.2] - 2020-05-22 ### Changed diff --git a/src/process_manager.c b/src/process_manager.c index 66deabfa..8df1ea06 100644 --- a/src/process_manager.c +++ b/src/process_manager.c @@ -33,12 +33,14 @@ struct process *process_create(ProcessSerialNumber psn) process->terminated = false; process->xpc = process_info.processType == 'XPC!'; GetProcessPID(&process->psn, &process->pid); + process->ns_application = workspace_application_create_running_ns_application(process); return process; } void process_destroy(struct process *process) { + workspace_application_destroy_running_ns_application(process); free(process->name); free(process); } diff --git a/src/process_manager.h b/src/process_manager.h index b0ea3fc6..04495ae5 100644 --- a/src/process_manager.h +++ b/src/process_manager.h @@ -17,6 +17,7 @@ struct process char *name; bool xpc; bool volatile terminated; + void *ns_application; }; struct process_manager diff --git a/src/workspace.h b/src/workspace.h index e7aba1fe..ae339c90 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -11,6 +11,8 @@ void workspace_event_handler_begin(void **context); void workspace_event_handler_end(void *context); struct process; +void *workspace_application_create_running_ns_application(struct process *process); +void workspace_application_destroy_running_ns_application(struct process *process); bool workspace_application_is_observable(struct process *process); bool workspace_application_is_finished_launching(struct process *process); void workspace_application_observe_finished_launching(void *context, struct process *process); diff --git a/src/workspace.m b/src/workspace.m index d9c39322..c0e5487f 100644 --- a/src/workspace.m +++ b/src/workspace.m @@ -20,9 +20,20 @@ void workspace_event_handler_end(void *context) [ws_context dealloc]; } +void *workspace_application_create_running_ns_application(struct process *process) +{ + return [NSRunningApplication runningApplicationWithProcessIdentifier:process->pid]; +} + +void workspace_application_destroy_running_ns_application(struct process *process) +{ + NSRunningApplication *application = process->ns_application; + if (application) [application release]; +} + void workspace_application_observe_finished_launching(void *context, struct process *process) { - NSRunningApplication *application = [NSRunningApplication runningApplicationWithProcessIdentifier:((struct process *)process)->pid]; + NSRunningApplication *application = process->ns_application; if (application) { [application addObserver:context forKeyPath:@"finishedLaunching" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew context:process]; } else { @@ -32,7 +43,7 @@ void workspace_application_observe_finished_launching(void *context, struct proc void workspace_application_observe_activation_policy(void *context, struct process *process) { - NSRunningApplication *application = [NSRunningApplication runningApplicationWithProcessIdentifier:process->pid]; + NSRunningApplication *application = process->ns_application; if (application) { [application addObserver:context forKeyPath:@"activationPolicy" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew context:process]; } else { @@ -42,30 +53,22 @@ void workspace_application_observe_activation_policy(void *context, struct proce bool workspace_application_is_observable(struct process *process) { - NSRunningApplication *application = [NSRunningApplication runningApplicationWithProcessIdentifier:process->pid]; - + NSRunningApplication *application = process->ns_application; if (application) { - bool result = [application activationPolicy] != NSApplicationActivationPolicyProhibited; - [application release]; - return result; + return [application activationPolicy] != NSApplicationActivationPolicyProhibited; + } else { + return false; } - - debug("%s: could not determine observability status for %s (%d)\n", __FUNCTION__, process->name, process->pid); - return false; } bool workspace_application_is_finished_launching(struct process *process) { - NSRunningApplication *application = [NSRunningApplication runningApplicationWithProcessIdentifier:process->pid]; - + NSRunningApplication *application = process->ns_application; if (application) { - bool result = [application isFinishedLaunching] == YES; - [application release]; - return result; + return [application isFinishedLaunching] == YES; + } else { + return false; } - - debug("%s: could not determine launch status for %s (%d)\n", __FUNCTION__, process->name, process->pid); - return false; } @implementation workspace_context @@ -146,8 +149,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N @try { [object removeObserver:self forKeyPath:@"activationPolicy"]; } @catch (NSException * __unused exception) {} - - [object release]; } } @@ -171,8 +172,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N @try { [object removeObserver:self forKeyPath:@"finishedLaunching"]; } @catch (NSException * __unused exception) {} - - [object release]; } } }