Захотелось разобраться как работает оконная система MacOS X изнутри. В Windows все понятно и документировано - цикл сообщений, API для создания окон и манипуляции их состоянием. В замечательной OS X все спрятано за красивым фреймворком Cocoa. Годы хардфакинга в MFC/WinAPI подсказывают, что принципы построения графической оболочки везде одинаковы. Потратил время, докопался до места откуда растут ноги.
Механизм взаимодействия графической подсистемы с пользовательским кодом
Если создать в XCode простейшее AppKit приложение и запустить его - получим пустое окно на экране. Чудес, как обычно, не бывает - окно должно быть создано неким API. За композицию окон в OS X отвечает подсистема с замысловатым названием Quartz. В списке процессов можно обнаружить WindowServer, это собственно ядро Quartz. Именно там происходит формирование картинки для устройства отображения (монитора). Гугление на тему создания окон в OS X привело меня на страничку Header file for undocumented CoreGraphics SPI. Изучив контент я сделал вывод, что существует библиотека Core Graphics с низкоуровневым API для взаимодействия с WindowServer. Дабы убедиться, что Cocoa использует этот API, я поставил точку останова на функцию _CGSCreateWindowInline
и запустил приложение. В результате получил такой стек вызовов:
#1 0x00007fff8fc8d64b in _CGSCreateWindowInline ()
#2 0x00007fff8fc8cd0b in CGSNewWindowWithOpaqueShape ()
#3 0x00007fff8be708e8 in _NSCreateWindowWithOpaqueShape2 ()
#4 0x00007fff8be6ed70 in -[NSWindow _commonAwake] ()
#5 0x00007fff8bf271c9 in -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] ()
#6 0x00007fff8bf26a18 in -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] ()
#7 0x00007fff8bf265ff in -[NSWindow orderWindow:relativeTo:] ()
#8 0x00007fff8be27c96 in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] ()
#9 0x00007fff8be06b7d in loadNib ()
#10 0x00007fff8be060a9 in +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] ()
#11 0x00007fff8be05ede in -[NSBundle(NSNibLoading) loadNibNamed:owner:topLevelObjects:] ()
#12 0x00007fff8be05cbe in +[NSBundle(NSNibLoading) loadNibNamed:owner:] ()
#13 0x00007fff8be0247f in NSApplicationMain ()
#14 0x00000001000011b2 in main at /Users/admin/Development/CocoaInspector/CocoaInspector/main.m:13
#15 0x00007fff932127e1 in start ()
OK, это то, что нам нужно. Осталось выяснить как Core Graphics взаимодействует с процессом WindowServer. Ассемблерный листинг функции _CGSCreateWindowInline
содержит инструкцию вызова системной процедуры mach_msg
, которая является основным способом межпроцессного взаимодействия в операционной системе OS X.
Выводы: Core Graphics является закрытой недокументированной библиотекой для взаимодействия с графическим сервером средствами ядра путем отправки и получения сообщений.