致力于所有喜欢低级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上操作Windows,我必须处于相同的过程中,即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)?
提前多多感谢!
答案 0 :(得分:5)
据我了解,X11使用自己的Windows服务器和通用堆栈。这就是为什么它可以运行没有特殊端口的X11应用程序。
它只有一层模仿Cocoa窗口的响应,以便它可以与通用接口通信。它不是伪装的Cocoa堆栈,它的X11堆栈表面上伪装成Cocoa。因此,它仅响应与Cocoa相关的消息的子集。
我认为要在X11中做任何严肃的事情,你必须从一开始就使用X11 API。换句话说,写一下就好像不打算在Mac OS上运行一样。
答案 1 :(得分:5)
所有X11.app源和其他内容(Xquartz)都可以在Apple's official site获得(当前版本2.3.5(服务器85.2))。 Windows创建的核心在于xpr subdirectory。
操纵窗口Xquartz使用Xplugin库(/usr/lib/libXplugin.dylib)。它的头文件/usr/include/Xplugin.h定义了xp_create_surface()等函数,它们使用私有CoreGraphics API创建窗口,如CGSNewWindowWithOpaqueShape()。可以找到未记录的CoreGraphicsPrivate.h或CSGPrivate.h,即逆向工程的结果over the Web。 Xplugin会在自己的哈希中记住这些Quartz窗口的id,并为它们返回一个不透明的整数(即xp_resource_id)。然后Xquartz将特定的XID与此xp_resource_id相关联,并将其返回给客户端。
Xplugin是封闭源代码,没有API可以通过xp_resource_id或XID返回原生Quartz drawable。
为了绘制使用私有CoreGraphics API创建的窗口,您必须使用这些私有API。有一个名为CGWindowContextCreate()的函数,它通过Quartz id为特定的本机窗口返回CGContextRef。可以使用此上下文在窗口上绘制。但要接收真实的上下文而不是NULL,您必须处于创建窗口的过程中。