feat(info): add fallback title detection on macOS

This commit is contained in:
Federico Terzi 2021-08-12 20:06:24 +02:00
parent 35d931e49c
commit e3dc943a73
4 changed files with 65 additions and 2 deletions

View File

@ -22,6 +22,7 @@ use std::os::raw::c_char;
#[link(name = "espansoinfo", kind = "static")]
extern "C" {
pub fn info_get_title(buffer: *mut c_char, buffer_size: i32) -> i32;
pub fn info_get_title_fallback(buffer: *mut c_char, buffer_size: i32) -> i32;
pub fn info_get_exec(buffer: *mut c_char, buffer_size: i32) -> i32;
pub fn info_get_class(buffer: *mut c_char, buffer_size: i32) -> i32;
}

View File

@ -21,7 +21,7 @@ use std::{ffi::CStr, os::raw::c_char};
use crate::{AppInfo, AppInfoProvider};
use self::ffi::{info_get_class, info_get_exec, info_get_title};
use self::ffi::{info_get_class, info_get_exec, info_get_title, info_get_title_fallback};
mod ffi;
@ -36,7 +36,7 @@ impl CocoaAppInfoProvider {
impl AppInfoProvider for CocoaAppInfoProvider {
fn get_info(&self) -> AppInfo {
AppInfo {
title: self.get_title(),
title: self.get_title().or_else(|| self.get_title_fallback()),
class: self.get_class(),
exec: self.get_exec(),
}
@ -88,4 +88,20 @@ impl CocoaAppInfoProvider {
None
}
}
// Fallback using Accessibility API instead of Carbon
fn get_title_fallback(&self) -> Option<String> {
let mut buffer: [c_char; 2048] = [0; 2048];
if unsafe { info_get_title_fallback(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
let string = string.to_string_lossy();
if !string.is_empty() {
Some(string.to_string())
} else {
None
}
} else {
None
}
}
}

View File

@ -23,6 +23,7 @@
#include <stdint.h>
extern "C" int32_t info_get_title(char * buffer, int32_t buffer_size);
extern "C" int32_t info_get_title_fallback(char * buffer, int32_t buffer_size);
extern "C" int32_t info_get_exec(char * buffer, int32_t buffer_size);
extern "C" int32_t info_get_class(char * buffer, int32_t buffer_size);

View File

@ -51,6 +51,51 @@ int32_t info_get_title(char *buffer, int32_t buffer_size)
return 0;
}
// Partially taken from: https://stackoverflow.com/questions/480866/get-the-title-of-the-current-active-window-document-in-mac-os-x/23451568#23451568
int32_t info_get_title_fallback(char *buffer, int32_t buffer_size)
{
@autoreleasepool {
// Get the process ID of the frontmost application.
NSRunningApplication* app = [[NSWorkspace sharedWorkspace] frontmostApplication];
pid_t pid = [app processIdentifier];
AXUIElementRef appElem = AXUIElementCreateApplication(pid);
if (!appElem) {
return -1;
}
// Get the accessibility element corresponding to the frontmost window
// of the frontmost application.
AXUIElementRef window = NULL;
if (AXUIElementCopyAttributeValue(appElem,
kAXFocusedWindowAttribute, (CFTypeRef*)&window) != kAXErrorSuccess) {
CFRelease(appElem);
return -2;
}
// Finally, get the title of the frontmost window.
CFStringRef title = NULL;
AXError result = AXUIElementCopyAttributeValue(window, kAXTitleAttribute,
(CFTypeRef*)&title);
// At this point, we don't need window and appElem anymore.
CFRelease(window);
CFRelease(appElem);
if (result != kAXErrorSuccess) {
// Failed to get the window title.
return -3;
}
if (CFStringGetCString(title, buffer, buffer_size, kCFStringEncodingUTF8)) {
CFRelease(title);
return 1;
} else {
return -4;
}
}
}
int32_t info_get_exec(char *buffer, int32_t buffer_size)
{
@autoreleasepool {