How to get the name and window id of the current in focus window on macOS and change its position in rust?

225 views Asked by At

I need to somehow get the name and window id of the current in focus window on macOS in rust. With this information I need to change the position and size of this window using rust.

I am working in a larger rust project and need to be able to keep it buildable with cargo and just use different implementations for this specific problem for different operation systems, but macOS seems to be bit harder than I thought. I am trying to wrap my head around Objective-C, core-foundation and the macOS windowing system. There are so many poorly documented parts in this problem that are really hard for someone like me, who has no experience with the macOS window management system. So any help is highly appriciated.

I have seen the following question for getting all open windows owner names, which is good starting point:
Getting window owner names via CGWindowListCopyWindowInfo in Rust

Nonetheless, I have absolutly no clue how to get something like this:
get current focused window id using objective c
in the same syntax.

I have also seen CGWindowListCreateDescriptionFromArray (https://developer.apple.com/documentation/coregraphics/1455215-cgwindowlistcreatedescriptionfro) in a response here:
How to get another application window's title, position and size in Mac OS without Accessibility API?
but have no idea how to properly call and process the response with:
https://crates.io/crates/core-foundation

I have also found this Apple Script, but have no idea, on how to integrate this properly with rust:
Controlling OSX windows

The farest I got so far is the following example. While getting the name works, getting the window id crashes the program with the following error message.

Signal: SIGABRT (signal SIGABRT)
Terminated due to signal 6

fn window_in_focus() -> Vec<String> {
    const OPTIONS: CGWindowListOption = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements;
    let window_list_info = unsafe { CGWindowListCopyWindowInfo(OPTIONS, kCGNullWindowID) };
    let count = unsafe { CFArrayGetCount(window_list_info) };

    let mut list = vec![];

    for i in 0..count {
        let dic_ref = unsafe { CFArrayGetValueAtIndex(window_list_info, i as isize) as CFDictionaryRef };

        let key = CFString::new("kCGWindowName");
        let mut value: *const c_void = std::ptr::null();

        if unsafe { CFDictionaryGetValueIfPresent(dic_ref, key.to_void(), &mut value) != 0 } {

            let cf_ref = value as CFStringRef;
            let c_ptr = unsafe { CFStringGetCStringPtr(cf_ref, kCFStringEncodingUTF8) };
            if !c_ptr.is_null() {
                let c_result = unsafe { CStr::from_ptr(c_ptr) };
                let result = String::from(c_result.to_str().unwrap());
                list.push(result);
            }

        }

        let window_layer_key = CFString::new("kCGWindowLayer");
        let mut window_layer: *const c_void = std::ptr::null();

        if unsafe { CFDictionaryGetValueIfPresent(dic_ref, window_layer_key.to_void(), &mut window_layer) != 0 } {

            let cf_ref = window_layer as CFStringRef;
            let c_ptr = unsafe { CFStringGetIntValue(cf_ref) };
            list.push(c_ptr.to_string());
        }
    }

    unsafe {
        CFRelease(window_list_info as CFTypeRef);
    }

    return list;
}
0

There are 0 answers