Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: list window in z order #173

Merged
merged 9 commits into from
Dec 22, 2024
Merged

feat: list window in z order #173

merged 9 commits into from
Dec 22, 2024

Conversation

nashaofu
Copy link
Owner

@nashaofu nashaofu mentioned this pull request Dec 14, 2024
@nashaofu
Copy link
Owner Author

Work seamlessly on Windows @louis030195 👍

@nashaofu
Copy link
Owner Author

The implementation method on macOS is incorrect, which can lead to multiple windows being in a focused state simultaneously.
The following code can obtain the currently focused application, but it cannot accurately obtain the window.

use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use objc::{class, msg_send, sel, sel_impl};

fn main() {
    unsafe {
        // 获取 NSWorkspace 类的实例
        let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
        
        // 获取当前前台应用
        let front_app: id = msg_send![workspace, frontmostApplication];

        println!("front_app {:?}", front_app);

        if front_app != nil {
            let app_name: id = msg_send![front_app, localizedName];
            let app_name_str = NSString::UTF8String(app_name);
            println!("当前聚焦的应用程序: {}", std::ffi::CStr::from_ptr(app_name_str).to_str().unwrap());
        } else {
            println!("无法获取当前聚焦的应用程序。");
        }
    }
}

@louis030195
Copy link
Contributor

The implementation method on macOS is incorrect, which can lead to multiple windows being in a focused state simultaneously. The following code can obtain the currently focused application, but it cannot accurately obtain the window.

use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use objc::{class, msg_send, sel, sel_impl};

fn main() {
    unsafe {
        // 获取 NSWorkspace 类的实例
        let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
        
        // 获取当前前台应用
        let front_app: id = msg_send![workspace, frontmostApplication];

        println!("front_app {:?}", front_app);

        if front_app != nil {
            let app_name: id = msg_send![front_app, localizedName];
            let app_name_str = NSString::UTF8String(app_name);
            println!("当前聚焦的应用程序: {}", std::ffi::CStr::from_ptr(app_name_str).to_str().unwrap());
        } else {
            println!("无法获取当前聚焦的应用程序。");
        }
    }
}

isnt window inside apps anyway?

@nashaofu
Copy link
Owner Author

nashaofu commented Dec 15, 2024

isnt window inside apps anyway?

An application may have multiple windows, but the system can only identify which application is currently in focus, not the specific window within that application that is focused.

However, I am confident that there are other methods to obtain this information. For instance, Electron can retrieve it.

@nashaofu
Copy link
Owner Author

MacOS can get a relatively accurate Focused window, but there are still some problems. For example, if an application has multiple windows and one of them is set to always stay on top, switching to another window within the same application may still retrieve information about the window that is always on top. To obtain accurate information about the focused window, accessibility permissions are likely required.

@nashaofu
Copy link
Owner Author

MacOS can get a relatively accurate Focused window, but there are still some problems. For example, if an application has multiple windows and one of them is set to always stay on top, switching to another window within the same application may still retrieve information about the window that is always on top. To obtain accurate information about the focused window, accessibility permissions are likely required.

f I return the window hierarchy, is the is_focused status no longer needed?

@louis030195
Copy link
Contributor

MacOS can get a relatively accurate Focused window, but there are still some problems. For example, if an application has multiple windows and one of them is set to always stay on top, switching to another window within the same application may still retrieve information about the window that is always on top. To obtain accurate information about the focused window, accessibility permissions are likely required.

f I return the window hierarchy, is the is_focused status no longer needed?

maybe

@nashaofu nashaofu changed the title feat: window focus feat: list window by z order Dec 20, 2024
@nashaofu nashaofu changed the title feat: list window by z order feat: list window in z order Dec 20, 2024
@nashaofu
Copy link
Owner Author

@louis030195 The return value of window::all() is already sorted by window hierarchy from top to bottom, and window.z() has been added.

use std::thread;
use xcap::Window;

fn main() {
    thread::sleep(std::time::Duration::from_secs(3));

    let windows = Window::all().unwrap();

    for window in windows.clone() {
        println!(
            "Window:\n id: {}\n title: {}\n app_name: {}\n pid: {}\n monitor: {:?}\n position: {:?}\n size {:?}\n state {:?}\n",
            window.id(),
            window.title(),
            window.app_name(),
            window.pid(),
            window.current_monitor().name(),
            (window.x(), window.y(), window.z()),
            (window.width(), window.height()),
            (window.is_minimized(), window.is_maximized())
        );
    }
}

@louis030195
Copy link
Contributor

@louis030195 The return value of window::all() is already sorted by window hierarchy from top to bottom, and window.z() has been added.

use std::thread;
use xcap::Window;

fn main() {
    thread::sleep(std::time::Duration::from_secs(3));

    let windows = Window::all().unwrap();

    for window in windows.clone() {
        println!(
            "Window:\n id: {}\n title: {}\n app_name: {}\n pid: {}\n monitor: {:?}\n position: {:?}\n size {:?}\n state {:?}\n",
            window.id(),
            window.title(),
            window.app_name(),
            window.pid(),
            window.current_monitor().name(),
            (window.x(), window.y(), window.z()),
            (window.width(), window.height()),
            (window.is_minimized(), window.is_maximized())
        );
    }
}

that's cool!

what happen in these situations:

  • macos, single monitor, one full screen app, one app on top of it
  • macos, single monitor, same app but multiple windows at different level on z:
Screenshot 2024-12-20 at 4 29 00 PM - macos, 2 monitors, 2 app full screen - etc. i don't remember behaviour on windows/linux

@nashaofu
Copy link
Owner Author

The results of these three test cases are in line with expectations. However, in macOS, the z-axis values of multiple windows may be identical, whereas in Linux and Windows, they are different. Do you wish for consistency across all platforms?

macos, single monitor, one full screen app, one app on top of it

截屏2024-12-21 15 39 08
Window:
 id: 2843
 title: Developer Tools - file:///Users/nsf/w/screenshots/packages/react-screenshots/electron/electron.html
 app_name: Electron
 pid: 1037
 monitor: "Monitor #41028"
 position: (808, 212, 0)
 size (800, 628)
 state (false, false)

Window:
 id: 2817
 title: 
 app_name: Electron
 pid: 1037
 monitor: "Monitor #15793"
 position: (0, -44, 0)
 size (1792, 44)
 state (false, false)

Window:
 id: 2815
 title: nashaofu (nashaofu) · GitHub
 app_name: Electron
 pid: 1037
 monitor: "Monitor #41028"
 position: (0, 0, 0)
 size (1792, 1120)
 state (false, true)

macos, single monitor, same app but multiple windows at different level on z:

The upper level window z is larger
15 40 39

Window: # top window
 id: 2405
 title: 桌面
 app_name: 访达
 pid: 365
 monitor: "Monitor #41028"
 position: (600, 224, 0)
 size (920, 436)
 state (false, false)

Window:
 id: 2400
 title: 最近使用
 app_name: 访达
 pid: 365
 monitor: "Monitor #41028"
 position: (436, 169, 0)
 size (920, 436)
 state (false, false)

macos, 2 monitors, 2 app full screen - etc. i don't remember behaviour on windows/linux

The activated window level is higher,Electron is actived.

Window: # active window
 id: 2584
 title: 
 app_name: Electron
 pid: 80402
 monitor: "Monitor #41028"
 position: (-367, -1484, 0)
 size (2560, 44)
 state (false, false)

Window:
 id: 2338
 title: nashaofu (nashaofu) · GitHub
 app_name: Electron
 pid: 80402
 monitor: "Monitor #15793"
 position: (-367, -1440, 0)
 size (2560, 1440)
 state (false, true)

Window:
 id: 2114
 title: 
 app_name: Code
 pid: 63785
 monitor: "Monitor #15793"
 position: (0, -44, 0)
 size (1792, 44)
 state (false, false)

Window:
 id: 2009
 title: window_capture.rs — xcap
 app_name: Code
 pid: 63785
 monitor: "Monitor #41028"
 position: (0, 0, 0)
 size (1792, 1120)
 state (false, true)

@nashaofu
Copy link
Owner Author

nashaofu commented Dec 21, 2024

The results of these three test cases are in line with expectations. However, in macOS, the z-axis values of multiple windows may be identical, whereas in Linux and Windows, they are different. Do you wish for consistency across all platforms?

After consideration, the Z value will still remain unique, just like in Windows and Linux.
#179

@nashaofu nashaofu merged commit 5457eb2 into master Dec 22, 2024
1 of 4 checks passed
@nashaofu nashaofu deleted the fix-pr branch December 22, 2024 02:17
@louis030195
Copy link
Contributor

louis030195 commented Jan 7, 2025

https://youtu.be/9UDkURcu3Xk

@nashaofu fyi this does not work on macos

minimized / maximized is always false and z is showing 0 even though it's in the background

version 0.2.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants