Mac OS X Window Server против X11: безумная задача

Посвящается всем, кто любит низкоуровневый оконный сервер (CoreGraphicsPrivate.h и т. Д.), X11 на Mac, SIMBL и другие безумные вещи :)

На Mac есть простое приложение с эмуляцией X11 (например, xterm, xeyes и т. Д.) С одним окном. Во время работы X11 каким-то образом создает собственное окно Quartz для представления этого эмулированного приложения, и это окно доступно через Quartz Window Services, так что я могу получить его CSWindowID, заголовок, положение, размер и PID владельца (PID X11.app). Но он не поддерживает Accessibility API, поэтому нет возможности управлять им (за исключением, возможно, частных функций Core Graphichs из того же процесса).


Теперь вот задача:

Мне нужно разместить дополнительный NSView (или просто нарисовать что-нибудь) в таком окне. Я имею в виду родное окно Quartz, которое появилось в результате эмуляции X11 какого-то приложения. Я знаю, что для управления окнами на Mac я должен быть в том же процессе, то есть X11.app.


Я написал плагин SIMBL, который вторгается в процесс X11.app.

Там я могу вызвать [NSApp windows], но все время получаю ровно 2 NSWindows, которые не имеют ничего общего с окнами реальных приложений. Их даже не видно на экране.

Тем не менее, когда я вызываю NSWindowList (), я получаю все, что мне нужно (идентификаторы окон для окон X11) и даже больше (идентификаторы окон из других приложений).

Когда у меня есть CSWindowID для окон, эмулируемых X11, я вызываю [NSApp windowWithWindowNumber:] (Cocoa) и HIWindowFromCGWindowID () (Carbon), но оба они возвращают ноль! Из того же процесса!

Кстати, все эти действия отлично работают, когда я вторгаюсь в процесс Safari и другие ...


Итак, вопросы:

  • Как X11 создал такие окна, которые недоступны из одного и того же процесса?

  • Как я могу получить указатели на окна X11 (NSWindow *, CGContextRef или, по крайней мере, что-нибудь ...) и разместить на них мою графику (я даже не говорю о NSViews)?


Заранее большое спасибо!


person shoumikhin    schedule 24.06.2010    source источник


Ответы (2)


Насколько я понимаю, X11 использует свой собственный сервер Windows и общий стек. Вот почему он может запускать приложения X11 без специальных портов.

У него есть только уровень ответов, который имитирует уровень окон Какао, так что он может взаимодействовать с общим интерфейсом. Это не замаскированный стек какао, это стек X11, внешне замаскированный под какао. Таким образом, он отвечает только на подмножество сообщений, связанных с Какао.

Я думаю, чтобы сделать что-нибудь серьезное в X11, вам нужно с самого начала использовать X11 API. Другими словами, пишите так, как будто он не предназначен для работы на Mac OS.

person TechZen    schedule 24.06.2010
comment
Итак, можно ли создать настоящее окно Quartz, но даже без WindowRef для него? Как же тогда X11 перемещает свои окна, когда получает события NSE, сворачивает их и так далее? Вы имеете в виду, что он хранит ссылки WindowsRef где-то глубоко в своем коде? - person shoumikhin; 24.06.2010
comment
Похоже, есть частный API для создания окон ... X11 использует libXplugin, а он, в свою очередь, использует такие функции, как CGSNewWindow () ... - person shoumikhin; 24.06.2010
comment
CGSNewWindow() является частью библиотеки SDL (Simple DirectMedia Library), которая представляет собой кроссплатформенную медиа / игровую библиотеку. см. libsdl.org/index.php Как я сказал, это не совсем Cocoa. - person TechZen; 25.06.2010
comment
ОК, а затем посмотрите: CGError CGSNewWindowWithOpaqueShape (CGSConnectionID cid, int always2, float x, float y, CGSRegionRef shape, CGSRegionRef opaqueShape, int unknown1, void * unknownPtr, int always32, CGSWindowID); * out - person shoumikhin; 29.06.2010
comment
На что я должен смотреть? Скорее, что я должен сделать из этого кода? - person TechZen; 30.06.2010
comment
Откройте /usr/lib/libXplugin.1.dylib с IDA Pro и посмотрите подпрограмму _xp_create_window. Вы увидите, что он использует CGSNewWindowWithOpaqueShape (), а затем запоминает свой результат в собственном хэше и возвращает непрозрачный идентификатор, известный как xp_window_id. Xquartz (привязки X-сервера для Mac) использует Xplugin для создания окон и, в свою очередь, связывает x_window_id с XID. - person shoumikhin; 30.06.2010
comment
Так что, в конце концов, все получилось так, как я думал. Он имеет настраиваемое внутреннее управление окнами и отображает его в Какао. - person TechZen; 30.06.2010

Все исходники X11.app и другие материалы (Xquartz) доступны по адресу официальный сайт Apple (текущая версия 2.3.5 (сервер 85.2)). Ядро создания окон лежит в подкаталог xpr.

Для управления окнами Xquartz использует библиотеку Xplugin (/usr/lib/libXplugin.dylib). Его заголовок, /usr/include/Xplugin.h, определяет такие функции, как xp_create_surface () и другие, которые создают окна с использованием частного API CoreGraphics, например CGSNewWindowWithOpaqueShape (). Недокументированный CoreGraphicsPrivate.h или CSGPrivate.h, результат обратного проектирования, можно найти через Интернет. Xplugin запоминает идентификаторы таких окон Quartz в своем собственном хэше и возвращает для них непрозрачное целое число (например, xp_resource_id). Затем Xquartz связывает конкретный XID с этим xp_resource_id и возвращает его клиенту.

Xplugin является закрытым исходным кодом и не имеет API для возврата собственного Quartz, который можно рисовать с помощью xp_resource_id или XID.

Чтобы использовать окно, созданное с помощью частного API CoreGraphics, вы должны использовать этот частный API. Существует функция с именем CGWindowContextCreate (), которая возвращает CGContextRef для конкретного собственного окна по его идентификатору Quartz. В этом контексте можно рисовать в окне. Но чтобы получить реальный контекст вместо NULL, вы должны находиться в процессе, создавшем окно.

person shoumikhin    schedule 24.06.2010
comment
Если это ответ на ваш вопрос, вы должны поставить галочку, чтобы система знала, что ответ был получен. - person TechZen; 30.06.2010