通过 OSX Accessibility API 获取窗口编号 [英] Getting Window Number through OSX Accessibility API

查看:31
本文介绍了通过 OSX Accessibility API 获取窗口编号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个可以在屏幕上移动第三方应用程序窗口的应用程序.

I am working on an application that moves windows of third party applications around on the screen.

要获得所有当前打开的窗口的概览,我使用

To get an overview of all currently open windows, I use

CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);

这将返回定义每个打开窗口的字典数组.这是返回的示例字典:

This returns an array of dictionaries defining every open window. Here's an exemplary dictionary returned:

{
    kCGWindowAlpha = 1;
    kCGWindowBounds =         {
        Height = 442;
        Width = 475;
        X = 3123;
        Y = "-118";
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 907184;
    kCGWindowName = Untitled;
    kCGWindowNumber = 7328;
    kCGWindowOwnerName = TextEdit;
    kCGWindowOwnerPID = 20706;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 2;
    kCGWindowWorkspace = 3;
},

字典充满了其他地方使用的好信息,但缺少可用于修改窗口位置的辅助功能对象.窗口由窗口编号清楚地标识.

The dictionary is full of good information used elsewhere but lacks an accessibility object that could be used to modify the windows' positions. Windows are clearly identified by the Window Number.

我现在使用 PID (kCGWindowOwnerPID) 为窗口的应用程序创建可访问性对象:

I am now using the PID (kCGWindowOwnerPID) to create an accessibility object for the window's application:

AXUIElementRef app = AXUIElementCreateApplication(pid);

接着使用 AXUIElementCopyAttributeValues 检索应用程序打开的所有窗口的列表:

Followed by retrieving a list of all windows the application has opened using AXUIElementCopyAttributeValues:

NSArray *result;

AXUIElementCopyAttributeValues(
                               (AXUIElementRef) app, 
                               kAXWindowsAttribute,
                               0,
                               99999,
                               (CFArrayRef *) &result
                               );

这有效并返回一个 AXUIElements 数组.这就是我被困的地方.似乎没有 API 调用来检索可访问性对象的窗口编号.有什么办法可以

This works and returns an array of AXUIElements. This is where I am stuck. There seems to be no API call to retrieve the Window Number of an accessibility object. Is there any way to either

a) 找到可访问性对象的窗口编号(最终遍历数组并找到正确的窗口)

a) Find the accessibility object's Window Number (to ultimately iterate over the array and find the right window)

b) 否则是否将 CGWindowListCopyWindowInfo 返回的数组中描述的窗口与 AXUIElementCopyAttributeValues 返回的辅助功能对象明确匹配?

b) Otherwise clearly match a window described in the array returned by CGWindowListCopyWindowInfo to the Accessibility Objects returned by AXUIElementCopyAttributeValues?

推荐答案

我们最终聘请了一位专门的辅助功能开发人员来完成这项任务.

We ended up hiring a dedicated Accessibility Developer for this task.

事实证明,如果不使用未记录的 API,就无法做到这一点(在我们的案例中是不行的).

It turns out there is no way to do this without using undocumented APIs (a no go in our case).

幸运的是,有一个实用的解决方法:

Luckily, there is a practical workaround:

遍历应用程序的所有打开窗口.获取他们的位置、大小和标题:

Loop over all open windows of the app. Get their position, size and title:

AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue);
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue);

接下来,将位置和大小转换为实际的CGPointCGSize值:

Next, convert the position and size into actual CGPoint and CGSize values:

AXValueGetValue(posValue, kAXValueCGPointType, &point);
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size);

将大小、位置和标题与CGWindowListCopyWindowInfo() 中对象返回的值进行比较.如果它们匹配,您可以放心地假设它是您正在寻找的窗口,并使用已经打开的 AXUIElement(在我们的例子中为 target)来工作.

Compare the size, position and title against the values returned by the object in CGWindowListCopyWindowInfo(). If they match, you can safely assume it's the window you were looking for and use the already open AXUIElement (target in our case) to work it.

在 OSX 上循环遍历所有打开的窗口的开销可以忽略不计.同时打开的窗口数量的上限非常低.

The overhead for looping through all open windows turns out to be negligible on OSX. There is a pretty low cap on how many windows are open at the same time.

此外,虽然这不是 100% 准确(可能 2 个窗口具有相同的位置、大小和标题),但我们目前在实际使用中还没有遇到过这种情况.

Also, while this is not 100% accurate (it is possible that 2 windows have the same position, size and title), we haven't encountered any situation in real usage where this happens so far.

这篇关于通过 OSX Accessibility API 获取窗口编号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆