According to the OS X v10.11 API Diffs document, the CGEventTapCreateForPid() function was added to CGEvent.h in El Capitan. It appears to be intended as a modern alternative to the CGEventTapCreateForPSN() function that has been around since the beginning. The parameters are the same except for the substitution of the new pid parameter for the old processSerialNumber parameter.
However, the new Pid version doesn't work the same as the old PSN version, and it is therefore very dangerous to simply call the Pid version whenever an application is running under El Capitan. I can find no explanation of the intended usage of the new function anywhere, not even in the CGEvent.h header comments. Can somebody explain how the Pid version is supposed to be used?
The CGEvent.h header does reveal several oddities about the new Pid function:
1. The "new" Pid function is listed as CG_AVAILABLE_STARTING in Mac OS X v10.4, not v10.11. Apparently it has been around since the beginning after all, despite what the API Diffs document says. Is this really true, or is it just a sign that the comments were not updated?
2. The callback and userInfo parameters are not marked __nullable in the new Pid function, although they are marked __nullable in the old PSN function. Why the change? This appears to make it impossible to initialize an "empty" event tap with the new Pid function and then configure and install it later, as I can do with the old function. Also, of course, it is a trap for the unwary because the difference is not called out or explained in the comments.
3. The comment for the old and new functions together has not been updated. It refers only to the old PSN function and says nothing about the new Pid function.
In my free developer utility Event Taps Testbench < http://pfiddlesoft.com/eventtapstestbench>, I call the old PSN function to create an "empty" event tap, then I let the user set the parameter values in the application's GUI and click an Install button to configure and install it. It works perfectly. I convert the temporary Pid value of 0 to the equivalent PSN value using GetProcessForPid(), and the old PSN function returns a real CFMachPortRef.
In the new version of Event Taps Testbench that I am developing now, I call the new Pid function instead when running under El Capitan. It does not work. Either the Pid value of 0 or the two null parameters (which are not marked __nullable) result in a CFMachPortRef return value of 0. That in turn prevents me from creating the run loop source that I need in order to install the tap.
The fix is easy: I'll just keep using the old PSN function. But why is there a new Pid function that doesn't work the same? And how long will the old PSN function stick around? |