Skip to content

Commit

Permalink
#2190 #2168 #2194 change how background processes are detected
Browse files Browse the repository at this point in the history
  • Loading branch information
koekeishiya committed Mar 30, 2024
1 parent 7188d58 commit 82727a2
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 57 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed
- Consecutive window resize operations would not work correctly because it used a cached value for the window frame [#2182](https://github.com/koekeishiya/yabai/issues/2182)
- Fix weird delay caused by interaction between macOS System APIs on Sonoma when using `--insert` in combination with other commands in rapid succession [#2188](https://github.com/koekeishiya/yabai/issues/2188)
- Whitelist wezterm-gui process for management because it incorrectly identifies as a background-only process [#2190](https://github.com/koekeishiya/yabai/issues/2190)
- Change how background processes are detected and handled [#2190](https://github.com/koekeishiya/yabai/issues/2190) [#2168](https://github.com/koekeishiya/yabai/issues/2168) [#2194](https://github.com/koekeishiya/yabai/issues/2194)

## [7.0.3] - 2024-03-22
### Changed
Expand Down
20 changes: 10 additions & 10 deletions src/event_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,39 +56,39 @@ static EVENT_HANDLER(APPLICATION_LAUNCHED)
return;
}

if (!workspace_application_is_observable(process)) {
debug("%s: %s (%d) is not observable, subscribing to activationPolicy changes\n", __FUNCTION__, process->name, process->pid);
workspace_application_observe_activation_policy(g_workspace_context, process);
if (!workspace_application_is_finished_launching(process)) {
debug("%s: %s (%d) is not finished launching, subscribing to finishedLaunching changes\n", __FUNCTION__, process->name, process->pid);
workspace_application_observe_finished_launching(g_workspace_context, process);

//
// NOTE(koekeishiya): Do this again in case of race-conditions between the previous check and key-value observation subscription.
// Not actually sure if this can happen in practice..
//

if (workspace_application_is_observable(process)) {
if (workspace_application_is_finished_launching(process)) {
@try {
NSRunningApplication *application = __atomic_load_n(&process->ns_application, __ATOMIC_RELAXED);
if (application && [application observationInfo]) {
[application removeObserver:g_workspace_context forKeyPath:@"activationPolicy" context:process];
[application removeObserver:g_workspace_context forKeyPath:@"finishedLaunching" context:process];
}
} @catch (NSException * __unused exception) {}
} else { return; }
}

if (!workspace_application_is_finished_launching(process)) {
debug("%s: %s (%d) is not finished launching, subscribing to finishedLaunching changes\n", __FUNCTION__, process->name, process->pid);
workspace_application_observe_finished_launching(g_workspace_context, process);
if (!workspace_application_is_observable(process)) {
debug("%s: %s (%d) is not observable, subscribing to activationPolicy changes\n", __FUNCTION__, process->name, process->pid);
workspace_application_observe_activation_policy(g_workspace_context, process);

//
// NOTE(koekeishiya): Do this again in case of race-conditions between the previous check and key-value observation subscription.
// Not actually sure if this can happen in practice..
//

if (workspace_application_is_finished_launching(process)) {
if (workspace_application_is_observable(process)) {
@try {
NSRunningApplication *application = __atomic_load_n(&process->ns_application, __ATOMIC_RELAXED);
if (application && [application observationInfo]) {
[application removeObserver:g_workspace_context forKeyPath:@"finishedLaunching" context:process];
[application removeObserver:g_workspace_context forKeyPath:@"activationPolicy" context:process];
}
} @catch (NSException * __unused exception) {}
} else { return; }
Expand Down
24 changes: 0 additions & 24 deletions src/process_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ static TABLE_COMPARE_FUNC(compare_psn)
return psn_equals(key_a, key_b);
}

static const char *process_name_whitelist[] =
{
"System Information",
"zathura",
"wezterm-gui",
};

static const char *process_name_blacklist[] =
{
"Übersicht",
Expand Down Expand Up @@ -50,23 +43,6 @@ struct process *process_create(ProcessSerialNumber psn)
return NULL;
}

if (process_info.processMode & modeOnlyBackground) {
bool whitelisted = false;

for (int i = 0; i < array_count(process_name_whitelist); ++i) {
if (string_equals(process_name, process_name_whitelist[i])) {
whitelisted = true;
break;
}
}

if (!whitelisted) {
debug("%s: background-only service '%s' detected! ignoring..\n", __FUNCTION__, process_name);
free(process_name);
return NULL;
}
}

for (int i = 0; i < array_count(process_name_blacklist); ++i) {
if (string_equals(process_name, process_name_blacklist[i])) {
debug("%s: %s is blacklisted! ignoring..\n", __FUNCTION__, process_name);
Expand Down
3 changes: 2 additions & 1 deletion src/process_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ struct process
ProcessSerialNumber psn;
pid_t pid;
char *name;
bool volatile terminated;
void *ns_application;
uint32_t policy;
bool volatile terminated;
};

struct process_manager
Expand Down
20 changes: 13 additions & 7 deletions src/window_manager.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern mach_port_t g_bs_port;
extern uint8_t *g_event_bytes;
extern struct event_loop g_event_loop;
extern void *g_workspace_context;
extern struct process_manager g_process_manager;
extern struct mouse_state g_mouse_state;
extern double g_cv_host_clock_frequency;
Expand Down Expand Up @@ -2526,14 +2527,19 @@ void window_manager_begin(struct space_manager *sm, struct window_manager *wm)
while (bucket) {
if (bucket->value) {
struct process *process = bucket->value;
struct application *application = application_create(process);

if (application_observe(application)) {
window_manager_add_application(wm, application);
window_manager_add_existing_application_windows(sm, wm, application, -1);
if (workspace_application_is_observable(process)) {
struct application *application = application_create(process);

if (application_observe(application)) {
window_manager_add_application(wm, application);
window_manager_add_existing_application_windows(sm, wm, application, -1);
} else {
application_unobserve(application);
application_destroy(application);
}
} else {
application_unobserve(application);
application_destroy(application);
debug("%s: %s (%d) is not observable, subscribing to activationPolicy changes\n", __FUNCTION__, process->name, process->pid);
workspace_application_observe_activation_policy(g_workspace_context, process);
}
}

Expand Down
31 changes: 17 additions & 14 deletions src/workspace.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ bool workspace_application_is_observable(struct process *process)
{
NSRunningApplication *application = __atomic_load_n(&process->ns_application, __ATOMIC_RELAXED);
if (application) {
return [application activationPolicy] != NSApplicationActivationPolicyProhibited;
process->policy = [application activationPolicy];
return process->policy == NSApplicationActivationPolicyRegular;
} else {
process->policy = NSApplicationActivationPolicyProhibited;
return false;
}
}
Expand Down Expand Up @@ -182,14 +184,11 @@ - (void)dealloc
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"activationPolicy"]) {
id result = [change objectForKey:NSKeyValueChangeNewKey];
if ([result intValue] != NSApplicationActivationPolicyProhibited) {
struct process *process = context;
assert(!process->terminated);

debug("%s: activation policy changed for %s (%d)\n", __FUNCTION__, process->name, process->pid);
event_loop_post(&g_event_loop, APPLICATION_LAUNCHED, process, 0);
struct process *process = context;
assert(!process->terminated);

id result = [change objectForKey:NSKeyValueChangeNewKey];
if ([result intValue] != process->policy) {
//
// :WorstApiEverMade
//
Expand All @@ -202,18 +201,19 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
@try {
[object removeObserver:self forKeyPath:@"activationPolicy" context:process];
} @catch (NSException * __unused exception) {}

process->policy = [result intValue];
debug("%s: activation policy changed for %s (%d)\n", __FUNCTION__, process->name, process->pid);
event_loop_post(&g_event_loop, APPLICATION_LAUNCHED, process, 0);
}
}

if ([keyPath isEqualToString:@"finishedLaunching"]) {
struct process *process = context;
assert(!process->terminated);

id result = [change objectForKey:NSKeyValueChangeNewKey];
if ([result intValue] == 1) {
struct process *process = context;
assert(!process->terminated);

debug("%s: %s (%d) finished launching\n", __FUNCTION__, process->name, process->pid);
event_loop_post(&g_event_loop, APPLICATION_LAUNCHED, process, 0);

//
// :WorstApiEverMade
//
Expand All @@ -226,6 +226,9 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
@try {
[object removeObserver:self forKeyPath:@"finishedLaunching" context:process];
} @catch (NSException * __unused exception) {}

debug("%s: %s (%d) finished launching\n", __FUNCTION__, process->name, process->pid);
event_loop_post(&g_event_loop, APPLICATION_LAUNCHED, process, 0);
}
}
}
Expand Down

0 comments on commit 82727a2

Please sign in to comment.