问题描述
专为所有喜欢低级Window Server(CoreGraphicsPrivate.h等),X11在Mac,SIMBL和其他疯狂的东西:)
有一个简单的X11模拟的应用程序在Mac(像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 !从同一个过程!
BTW,当我侵入Safari进程和其他人的时候,所有这些操作都很好。
$ b $因此,问题是:
-
X11如何创建
-
如何获取指向X11窗口的指针(NSWindow *,CGContextRef,或者,至少,
$ b
所有的X11.app源代码和其他东西Xquartz)可在(当前版本2.3.5(服务器85.2))。 Windows创建的核心在于。
操作窗口Xquartz使用Xplugin库(/usr/lib/libXplugin.dylib)。它的头,/usr/include/Xplugin.h,定义像xp_create_surface()和其他,使用私人CoreGraphics API,如CGSNewWindowWithOpaqueShape()创建窗口的函数。未记录的CoreGraphicsPrivate.h或CSGPrivate.h,反向工程的结果,可以找到。 Xplugin在其自己的哈希中记住这样的Quartz窗口的id,并为它们返回一个不透明的整数(即xp_resource_id)。然后Xquartz将一个特定的XID与这个xp_resource_id关联起来,并将其返回给客户端。
Xplugin是封闭的源代码,没有API可以通过xp_resource_id或XID来返回。
为了绘制一个使用私有CoreGraphics API创建的窗口,你必须使用这些私有API。有一个名为CGWindowContextCreate()的函数,它通过其Quartz id为特定的本地窗口返回CGContextRef。可以使用此上下文在窗口上绘制。但是为了接收真正的上下文而不是NULL,你必须在一个进程中创建窗口。
Dedicated to all who likes low-level Window Server (CoreGraphicsPrivate.h, etc), X11 on Mac, SIMBL and other crazy stuff :)
There's a simple X11-emulated application on Mac (like xterm, xeyes and so on) with one window. While running, X11 somehow creates a native Quartz window to represent this emulated application, and this window is accessible via Quartz Window Services so that I can get its CSWindowID, title, position, size and owner's PID (PID of X11.app). But it does not support Accessibility API, so there's no way to control it (except, maybe Core Graphichs private functions from the same process).
Now, here's the task:
I need to host an additional NSView (or just draw something) upon such a window. I mean a native Quartz window, which appeared as a result of X11 emulating some application. I know, to manipulate windows on Mac I must be in the same process, i.e. X11.app.
I wrote a SIMBL plug-in which intrudes into X11.app process.
There I can call [NSApp windows], but all the time I'm getting exactly 2 NSWindows which have nothing in common with real applications' windows. They are not even visible on the screen.
Nevertheless, when I call NSWindowList(), I get anything I need (window IDs for X11 windows) and even more (window IDs from other applications).
When I've got CSWindowIDs for X11-emulated windows, I call [NSApp windowWithWindowNumber: ] (Cocoa) and HIWindowFromCGWindowID() (Carbon), but they both return nil! From the very same process!
BTW, all this actions work perfectly when I intrude into Safari process and others...
So, the questions are:
How did X11 create such windows which are not accessible from the very same process?
How can I get pointers to X11 windows (NSWindow *, CGContextRef, or, at least, anything...) and host my graphics (I don't even speak about NSViews) upon them?
Thanks a lot in advance!
All the X11.app sources and other stuff (Xquartz) are available at Apple's official site (current version 2.3.5 (server 85.2)). The core of windows creation lies in xpr subdirectory.
To manipulate windows Xquartz uses Xplugin library (/usr/lib/libXplugin.dylib). Its header, /usr/include/Xplugin.h, defines functions like xp_create_surface() and others, which create windows using private CoreGraphics API, like CGSNewWindowWithOpaqueShape(). Undocumented CoreGraphicsPrivate.h or CSGPrivate.h, the result of reverse engineering, can be found over the Web. Xplugin remembers ids of such Quartz windows in its own hash and returns an opaque integer (i.e., xp_resource_id) for them. Then Xquartz associates a particular XID with this xp_resource_id and returns it to a client.
Xplugin is closed source and has no API to return native Quartz drawable by xp_resource_id or XID.
In order to draw upon a window which was created with private CoreGraphics API you have to use those private API. There's a function, named CGWindowContextCreate(), which returns CGContextRef for a particular native window by its Quartz id. It is possible to draw on the window using this context. But to receive the real context instead of NULL, you must be in a process, which created the window.
这篇关于Mac OS X窗口服务器与X11:疯狂的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!