OSX/Objective-C窗口管理:操纵框架和其他应用程序的可见性 [英] OSX / Objective-C Window Management: manipulate the frames & visibility of other applications

查看:116
本文介绍了OSX/Objective-C窗口管理:操纵框架和其他应用程序的可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个系统工具/应用程序,它具有帮助进行窗口管理的能力.考虑到OSX的安全沙箱,如果确实可以实现以下主题,我将尝试查找有关文档.

  • 显示名称为&的正在运行的应用程序的列表图标,并允许用户选择一个
  • 从我的应用程序(带有动画)操纵所述应用程序窗口的框架(例如,调整大小,重新定位)-尽管我认为一旦执行实际更改,这将变得微不足道了
  • 从任务管理器等隐藏或显示这些应用程序.
  • 能够启动(或终止)给定应用程序的实例

在我看来, Quicksilver 可以完成许多这些工作,但是缺乏AppStore可用性使我怀疑它是否可以在保留在OSX沙箱中的同时执行此操作.

解决方案

有很多软件可以进行窗口管理.您可以查看我一直在使用的平铺窗口管理器,称为 Amethyst .诸如此类的软件背后的基本思想取决于可访问性(您可以在此处).作为快速概述,API通过获取对具有属性(隐藏,位置,大小等)的可访问性元素(应用程序,窗口,按钮,文本字段等)的引用来工作.

作为一个例子,假设您要将每个正在运行的应用程序中的所有窗口移到屏幕的左上角.该代码可能看起来像

for (NSRunningApplication *runningApplication in [[NSWorkspace sharedWorkspace] runningApplications]) {
    AXUIElementRef applicationRef = AXUIElementCreateApplication([runningApplication processIdentifier]);
    CFArrayRef applicationWindows;
    AXUIElementCopyAttributeValues(applicationRef, kAXWindowsAttribute, 0, 100, &applicationWindows);

    if (!applicationWindows) continue;

    for (CFIndex i = 0; i < CFArrayGetCount(applicationWindows); ++i) {
        AXUIElementRef windowRef = CFArrayGetValueAtIndex(applicationWindows, i);
        CGPoint upperLeft = { .x = 0, .y = 0 };
        AXValueRef positionRef = AXValueCreate(kAXValueCGPointType, &upperLeft);
        AXUIElementSetAttributeValue(windowRef, kAXPositionAttribute, positionRef);
    }
}

其中说明了如何获取对应用程序及其窗口的引用,如何从可访问性元素中复制属性以及如何设置可访问性元素的属性.

NSWorkspace中记录了用于启动和终止应用程序的各种通知,并且可访问性框架也对应用程序创建或销毁窗口,或窗口小型化或小型化之类的东西具有某种通知. /p>

动画化窗口更改并非易事,尽管有可能,但我还没有弄清楚该如何做.如果不使用私有API,可能根本不可能.但是您列出的其他内容也应该可行.例如,可以通过在应用程序可访问性元素上设置kAXHiddenAttribute来隐藏应用程序.实际上,可以通过-[NSWorkspace launchApplication:]启动应用程序.

请注意,使用辅助功能需要用户在System Preferences > Accessibility中打开Enable access for assistive devices.

I would like to create a system tool / application which has the capacity to aid in window management. I'm trying to find documentation about the following topics, if they are indeed possible given the security sandboxing of OSX.

  • Show a list of running applications with the name & icon, and allow the user to choose one
  • Manipulate the frame(s) of said application's windows (eg, resize, reposition) from my app (with animations -- though I assume this will be trivial once I can perform the actual change)
  • Hide or show these applications from task managers, etc.
  • Be able to launch (or terminate) instances of the given application

It seems to me that Quicksilver accomplishes many of these things, but the lack of AppStore availability makes me wonder if it possible to do this while remaining in the OSX sandbox.

解决方案

There are a lot of pieces of software out there that do window management. You can check out a tiling window manager I've been hacking on called Amethyst. The basic idea behind software like this relies on Accessibility (which you can find documentation for here). As a quick overview the APIs work by acquiring references to accessibility elements (applications, windows, buttons, text fields, etc.) which have properties (hidden, position, size, etc.), some of which are writable.

As an example let's say that you wanted to move all windows in every running application to the upper left corner of the screen. That code might look like

for (NSRunningApplication *runningApplication in [[NSWorkspace sharedWorkspace] runningApplications]) {
    AXUIElementRef applicationRef = AXUIElementCreateApplication([runningApplication processIdentifier]);
    CFArrayRef applicationWindows;
    AXUIElementCopyAttributeValues(applicationRef, kAXWindowsAttribute, 0, 100, &applicationWindows);

    if (!applicationWindows) continue;

    for (CFIndex i = 0; i < CFArrayGetCount(applicationWindows); ++i) {
        AXUIElementRef windowRef = CFArrayGetValueAtIndex(applicationWindows, i);
        CGPoint upperLeft = { .x = 0, .y = 0 };
        AXValueRef positionRef = AXValueCreate(kAXValueCGPointType, &upperLeft);
        AXUIElementSetAttributeValue(windowRef, kAXPositionAttribute, positionRef);
    }
}

Which illustrates how you get references to applications and their windows, how to copy attributes from an accessibility element, and how to set attributes of an accessibility element.

There are a variety of notifications documented in NSWorkspace for the launching and termination of applications, and the accessibility framework also has a sense of notifications for things like an application creating or destroying windows, or a window miniaturizing or deminiaturizing.

Animating the window changes is non-trivial and I haven't figured out how to do it yet, though it may be possible. It may not be possible at all without hitting private APIs. But the other things you have listed should be possible. Hiding an application, for example, could be done by setting the kAXHiddenAttribute on the application accessibility element. Launching an application can actually be done via -[NSWorkspace launchApplication:].

Note that the use of accessibility necessitates that the user have Enable access for assistive devices turned on in System Preferences > Accessibility.

这篇关于OSX/Objective-C窗口管理:操纵框架和其他应用程序的可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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