8

In Mac OS X Lion CARemoteLayerServer and CARemoteLayerClient were added to QuartzCore. I've been trying to investigate if they'd be suitable for splitting a graphical application between multiple processes, but without success.

I can use them successfully within a single process, with some code along the lines of this:

- (void)buildLayerSingleProcess
{
    CARemoteLayerServer *server = [CARemoteLayerServer sharedServer];

    self.client = [[CARemoteLayerClient alloc] initWithServerPort: server.serverPort];    
    uint32_t clientID = self.client.clientId;    

    CALayer *layer1 = [CALayer layer];
    layer1.bounds = CGRectMake(0.0, 0.0, 100.0, 100.0);

    CGColorRef color = CGColorCreateGenericRGB(0.4, 0.2, 0.3, 1.0);
    [layer1 setBackgroundColor: color];
    CFRelease(color);

    [layer1 setOpacity: 0.75];
    [layer1 setBorderWidth: 5.0f];

    layer1.position = CGPointMake([[self.window contentView] frame].size.width / 2.0, [[self.window contentView] frame ].size.height / 2.0);

    self.client.layer = layer2;

    CALayer *servedLayer = [CALayer layerWithRemoteClientId: self.client.clientId];    
    [[[self.window contentView] layer] addSublayer: servedLayer];
}

Which is nice, but I'd like to try and do something similar between processes. The fact that server.serverPort is of type mach_port_t implies that it'd be suitable for use between processes.

However, when I split that code up to run in two processes (either two individual apps, or a main process and an XPC service), when I try to initialise the CARemoteLayerClient with the mach_port_t from the server in the other process I get:

unable to register with server: 0x10000003

It may well be they're not suited for between random processes, but the use of mach_port_t kinda implies that.

Has anyone else had any success using these classes between processes?

Michael
  • 1,355
  • 2
  • 12
  • 15

1 Answers1

10

Yes, it's possible. Here is an example: https://github.com/krevis/RemoteLayerDemo

Run the app, press the "Get Remote Layer" button, and the service will be started and will give the app a green remote layer. (Oddly, it takes several seconds to appear -- no idea why.)

After that, the "Change Color" button sends a message to the service asking it to change the layer's color, which takes effect immediately, and even animates. The "Remove Remote Layer" button removes the layer; the service will then get terminated if you let it idle for a few seconds.

The hard part is passing the Mach port of the CARemoteLayerServer between processes. The mach_port_t that you see in your process is just a number; it only has meaning within your process. (Same idea as a pointer: pointers are just numbers, but you can't pass a pointer from one process to another, and expect them to point to the same thing.)

You'd think XPC could send Mach ports, but it can't. It would make this a lot easier!

Instead, you have to use Mach API to send the underlying Mach port around. In the demo, I'm using bootstrap_register in the app and and bootstrap_look_up in the service, using an agreed-upon name. This is not secure, because any other app in the same bootstrap context could find the port, but it's good enough for a demo. In reality you'd want to dive down to some uglier Mach calls.

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
  • Many thanks, particularly for the working demo, totally awesome. I was making a bad assumption about mach ports working like socket ports (which you can pass around). Clearly I need to spend more time with the Internals book! – Michael Feb 20 '12 at 09:05
  • Just tired and the demo no longer works - Xcode 7.2 - OSX 10.11.2 – Jimmy Jan 19 '16 at 10:48
  • 1
    Thanks for the reminder, I updated the code. For the record, the fix is to set the view's `layerUsesCoreImageFilters` property to YES. – Kurt Revis Jan 20 '16 at 05:37
  • Did you every find out why it takes seconds (around 6 on my machine) for the view to appear ? – Jimmy Jan 20 '16 at 09:53
  • No! It still happens, and I wish I knew why. If you find out let me know. – Kurt Revis Jan 21 '16 at 05:42
  • @KurtRevis Can you help me? I wrote a demo,want to display same thing on two procees.I draw something to the CARemoteLayerClient's layer,however the layer created on another process for CARemoteLayerServer didn't display the same thing,And idea how to update both layer? Your Demo failed to change the color on lastest MadOS 12 by the way. – KayWang Dec 27 '21 at 09:41
  • Sorry, at this point I've paged out everything I knew about this stuff. I agree that the demo no longer works, on macOS 12.1 (Apple Silicon). Ask Apple developer support, perhaps. – Kurt Revis Dec 28 '21 at 06:06