5

献给所有喜欢低级 Window Server(CoreGraphicsPrivate.h 等)、Mac 上的 X11、SIMBL 和其他疯狂东西的人 :)

Mac 上有一个简单的 X11 模拟应用程序(如 xterm、xeyes 等),只有一个窗口。在运行时,X11 以某种方式创建了一个原生 Quartz 窗口来表示这个模拟的应用程序,并且这个窗口可以通过 Quartz Window Services 访问,这样我就可以获得它的 CSWindowID、标题、位置、大小和所有者的 PID(X11.app 的 PID)。但它不支持 Accessibility API,因此无法控制它(除了,可能来自同一进程的 Core Graphichs 私有函数)。


现在,这是任务:

我需要在这样的窗口上托管一个额外的 NSView (或只是绘制一些东西)。我的意思是一个原生 Quartz 窗口,它是 X11 模拟某些应用程序的结果。我知道,要在 Mac 上操作窗口,我必须在同一个进程中,即 X11.app。


我写了一个 SIMBL 插件,它侵入了 X11.app 进程。

在那里我可以调用 [NSApp windows],但我总是得到 2 个 NSWindows,它们与实际应用程序的窗口没有任何共同之处。它们甚至在屏幕上都不可见。

然而,当我调用 NSWindowList() 时,我得到了我需要的任何东西(X11 窗口的窗口 ID)甚至更多(来自其他应用程序的窗口 ID)。

当我获得 X11 模拟窗口的 CSWindowID 时,我调用 [NSApp windowWithWindowNumber: ] (Cocoa) 和 HIWindowFromCGWindowID() (Carbon),但它们都返回 nil!来自同一个过程!

顺便说一句,当我侵入 Safari 进程和其他进程时,所有这些操作都能完美运行......


所以,问题是:

  • X11 是如何创建无法从同一个进程访问的窗口的?

  • 如何获得指向 X11 窗口(NSWindow *、CGContextRef 或至少是任何东西......)的指针并在它们上面托管我的图形(我什至不谈论 NSView)?


提前非常感谢!

4

2 回答 2

5

据我了解,X11 使用自己的 Windows 服务器和通用堆栈。这就是为什么它可以在没有特殊端口的情况下运行 X11 应用程序的原因。

它只有一层模仿 Cocoa 窗口的响应,以便它可以与通用界面通信。它不是伪装的 Cocoa 堆栈,而是表面伪装成 Cocoa 的 X11 堆栈。因此,它只响应 Cocoa 相关消息的子集。

我认为要在 X11 中做任何严肃的事情,你必须从一开始就使用 X11 API。换句话说,就好像它不打算在 Mac OS 上运行一样编写。

于 2010-06-24T14:09:03.017 回答
5

所有 X11.app 源代码和其他东西 (Xquartz) 都可以在Apple 的官方网站上找到(当前版本 2.3.5(服务器 85.2))。windows创建的核心在于xpr子目录

操作 Windows Xquartz 使用 Xplugin 库 (/usr/lib/libXplugin.dylib)。它的头文件 /usr/include/Xplugin.h 定义了 xp_create_surface() 等函数,它们使用私有 CoreGraphics API 创建窗口,如 CGSNewWindowWithOpaqueShape()。逆向工程的结果未记录的 CoreGraphicsPrivate.h 或 CSGPrivate.h 可以在 Web上找到。Xplugin 在其自己的哈希中记住此类 Quartz 窗口的 id,并为它们返回一个不透明的整数(即 xp_resource_id)。然后 Xquartz 将一个特定的 XID 与这个 xp_resource_id 相关联,并将其返回给客户端。

Xplugin 是封闭源代码,没有 API 可以通过 xp_resource_id 或 XID 返回原生 Quartz 可绘制对象。

为了绘制使用私有 CoreGraphics API 创建的窗口,您必须使用这些私有 API。有一个名为 CGWindowContextCreate() 的函数,它通过 Quartz id 返回特定本机窗口的 CGContextRef。可以使用此上下文在窗口上绘图。但是要接收真正的上下文而不是 NULL,您必须处于创建窗口的进程中。

于 2010-06-24T18:35:19.170 回答