dimusic / active-window-macos-example

Basic example of the MacOS app that gets currently active window in a loop
1 stars 0 forks source link

Unable to Print Active Window Information in a New Thread #1

Open zibo-chen opened 8 months ago

zibo-chen commented 8 months ago

Hello,

I'm currently using your library to monitor the active window on macOS. I've noticed that when I spawn a new thread and attempt to print the active window information within this thread, nothing gets printed out.

I suspect this might be due to the fact that GUI-related operations, such as getting the active window, must be performed on the main thread in macOS. If this is indeed the case, is there any way to circumvent this restriction and allow for the active window to be monitored in a separate thread?

Any help or guidance would be greatly appreciated.

Thank you.

dimusic commented 8 months ago

Are you saying the example from this repo doesn't work for you? It does spawn a new thread to poll the active window info and works fine for me.

There are basically two requirements to make it work on macOS:

zibo-chen commented 8 months ago

Hello @dimusic,

Thank you for your prompt response. I have indeed followed the example from the repository, and I'm aware of the two requirements you've mentioned for macOS:

  1. Subscribing to NSWorkspaceDidActivateApplicationNotification to receive application activation notifications.
  2. Ensuring that Screen Recording permission is manually enabled for the app.

Here is the code snippet I'm using within the main() function:

fn main() {
    thread::spawn(|| {
        unsafe {
            let cls = init_app_delegate_class();
            let app = NSApplication::sharedApplication(nil);

            let delegate: *mut Object = msg_send![cls, alloc];
            let delegate: *mut Object = msg_send![delegate, init];
            let delegate = StrongPtr::new(delegate);

            let _: () = msg_send![app, setDelegate: delegate];
            let _: () = msg_send![app, run];

            app.run();
        }
    });

    loop {

    }
}

When I run this code directly in the main thread, it works as expected and I can get the active window information. However, when I spawn a new thread as shown in the code above, the active window information is not printed out.

Could there be something I'm missing that's specific to threading with GUI operations on macOS? Or is there a different approach I should take to monitor the active window information in a separate thread?

Any further assistance or suggestions would be greatly appreciated.

dimusic commented 8 months ago

In your example you initialize the whole NSApplication instance in the child thread which I guess only supposed to happen in the main thread. However, I don't really know enough about app development for mac and there might be something else going on.

Is there a specific reason why you want to initialize app this way versus spawning a new thread in application_did_finish_launching like in my example?

zibo-chen commented 8 months ago

Thank you for pointing that out. The reason I'm trying to initialize the NSApplication instance in a child thread is that I'm looking to create a synchronous function that can be called when needed to get the active window information. The code provided in the example is blocking, and I'm aiming to modify it to suit this requirement.

However, I'm relatively new to Rust and macOS app development, so I'm not entirely sure how to go about this. If you have any suggestions on how to transform the example into a synchronous function that can be called on-demand, rather than having a continuous loop running in the background, I would greatly appreciate your guidance.