darlinghq / darling

Darwin/macOS emulation layer for Linux
http://www.darlinghq.org
GNU General Public License v3.0
11.22k stars 426 forks source link

Cocotron (AppKit) backend rework #937

Open LubosD opened 3 years ago

LubosD commented 3 years ago

This issue documents how Cocotron's integration to lower API layers should work.

Backends for X11 and Wayland

Event Processing

Another call stack:

1 com.apple.framework.IOKit 0x98832c8e IOHIDEventCreateWithBytes + 136
2 com.apple.framework.IOKit 0x9882f772 IOHIDEventCreateWithData + 61
3 com.apple.CoreGraphics 0x9b145a47 CGEventCreateFromDataAndSource + 3165
4 com.apple.CoreGraphics 0x9b144d88 CGSDecodeEventRecord + 105
5 com.apple.CoreGraphics 0x9b144d15 event_datagram_handler + 71
6 com.apple.CoreGraphics 0x9b14433a CGSDatagramReadStream::dispatch_next_datagram() + 806
7 com.apple.CoreGraphics 0x9b144007 CGSDatagramReadStream::dispatch_datagrams() + 47
8 com.apple.CoreGraphics 0x9b143e19 CGSDatagramReadStreamDispatchDatagramsWithData + 160
9 com.apple.CoreGraphics 0x9b143b2e CGSSnarfAndDispatchDatagrams + 432
10 com.apple.CoreGraphics 0x9b143864 CGSGetNextEventRecordInternal + 84
11 com.apple.CoreGraphics 0x9b1437cb CGEventCreateNextEvent + 39
12 com.apple.HIToolbox 0x927497bd PullEventsFromWindowServerOnConnection(unsigned int, unsigned char, __CFMachPortBoost*) + 99
13 com.apple.HIToolbox 0x92749726 MessageHandler(__CFMachPort*, void*, long, void*) + 52
14 com.apple.CoreFoundation 0x91fadfe8 __CFMachPortPerform + 440
15 com.apple.CoreFoundation 0x91fade15 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
16 com.apple.CoreFoundation 0x91fadd7b __CFRunLoopDoSource1 + 523
17 com.apple.CoreFoundation 0x91f9e4b2 __CFRunLoopRun + 2130
18 com.apple.CoreFoundation 0x91f9d9ea CFRunLoopRunSpecific + 394
19 com.apple.CoreFoundation 0x91f9d84b CFRunLoopRunInMode + 123
20 com.apple.HIToolbox 0x92740b5d RunCurrentEventLoopInMode + 259
21 com.apple.HIToolbox 0x92740777 ReceiveNextEventCommon + 163
22 com.apple.HIToolbox 0x9278baca AcquireNextEventInMode + 75
23 com.apple.HIToolbox 0x928db9da _AcquireNextEvent + 58
24 com.apple.HIToolbox 0x928c9324 RunApplicationEventLoop + 225

Call stack of event reception by AppKit:

6   com.apple.CoreFoundation           0x00007fff8e1eded8 CFRunLoopRunSpecific + 296
7   com.apple.HIToolbox                0x00007fff99fa1935 RunCurrentEventLoopInMode + 235
8   com.apple.HIToolbox                0x00007fff99fa1677 ReceiveNextEventCommon + 184
9   com.apple.HIToolbox                0x00007fff99fa15af _BlockUntilNextEventMatchingListInModeWithFilter + 71
10  com.apple.AppKit                   0x00007fff8ba0defa _DPSNextEvent + 1067
11  com.apple.AppKit                   0x00007fff8ba0d32a -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454

HIToolbox (Carbon) APIs return the event as an EventRef, which is converted to CGSEventRecord by AppKit using _GetEventPlatformEventRecord() and then to NSEvent using NSEvent _initWithCGSEvent.

NSEvent most likely contains both CGSEventRecord and EventRef: +[NSEvent eventWithCGEvent:] calls CGEventRecordPointer() and CreateEventWithCGEvent() to pass the return values to -[NSEvent _initWithCGSEvent:eventRef:].

Event Lifecycle

The lifecycle of a HID event seems to be:

  1. Receive event from X11/Wayland
  2. Convert it into a CGSEventRecord
  3. Post it to the Mach port returned by CGSGetEventPort()
  4. When the event is read with CGEventCreateNextEvent(), convert it into a CGEventRef
  5. Carbon then converts CGEventRef into an EventRef and stores it in an internal queue
  6. When AppKit calls Carbon to get the next EventRef, it then converts the EventRef into a CGSEventRecord
  7. The CGSEventRecord is converted to an NSEvent and passed through further processing
TheBrokenRail commented 3 years ago

Nice to see Wayland being worked on! What is the reasoning behind rewriting the X11 backend as part of CoreGraphics? Do some programs rely on internal CoreGraphics API calls?

LubosD commented 3 years ago

1) Yes 2) The main reason is to also properly integrate CGEvents and later Carbon.

noah-nuebling commented 1 year ago

Not sure this is useful but I just stepped through CreateEventWithCGEvent() and looking at the argument registers x0 - x8, one of the arguments is of type HIDEvent *, also known as its __bridged type IOHIDEventRef. Maybe that's the type of the event being created. You can find the source code for HIDEvent * in Apple's open source IOKit code.