TooTallNate / NodObjC

The Node.js ⇆ Objective-C bridge

Home Page:http://tootallnate.github.io/NodObjC

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Creating a CFTypeRef with NodObjC

nomeyer opened this issue · comments

Hi,

I'm trying to use OS X's accessibility framework. Specifically, I want to use the AXUIElementCopyAttributeValue from https://developer.apple.com/library/mac/documentation/ApplicationServices/Reference/AXUIElement_header_reference/index.html#//apple_ref/c/func/AXUIElementCopyAttributeValue.

The function requires a CFTypeRef argument (https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/index.html#//apple_ref/doc/c_ref/CFTypeRef), which I have no idea how to create using NodObjC. I found out that CFStringRef, CFArrayRef and others can be created with var objectRef = $.alloc($.NSString).ref() and var objectRef = $.alloc($.NSArray).ref(), but since CFTypeRef does not directly correspond with an NS object of some sort, I'm a bit lost.

Does anyone how how I'm supposed to create a CFTypeRef variable?

I've also tried using AXUIElementCopyAttributeValues instead of the function for a specific attribute, but electron crashes when I run the following (accessibility has already been enabled and $.AXAPIEnabled() returns true):

var $ = require('nodobjc')
const systemWideElement = $.AXUIElementCreateSystemWide();
var attributeRef = $.alloc($.NSArray).ref();
var outcome = $.AXUIElementCopyAttributeNames(systemWideElement, attributeRef);
console.log(outcome === $.kAXErrorSuccess);  // logs true

var attributes = attributeRef.deref();
console.log(attributes('objectAtIndex', 2));  // logs AXFocusedUIElement, the attribute of which I want to get the value

for (var i = 0; i < attributes('count'); i++) {
  var attrRef = attributes('objectAtIndex', i).ref();
  var valuesRef = $.alloc($.NSArray).ref();
  console.log($.AXUIElementCopyAttributeValues(systemWideElement, attrRef, i.toString(), '9999', valuesRef) === $.kAXErrorSuccess);  // electron crashes here on the first iteration of the loop
  var values = valuesRef.deref();
  console.log(values);
}

Help getting either approach to work would be greatly appreciated. Thanks!

@nomeyer Did you find a solution for this? I'm running into the same problem with

const appRef = AXUIElementCreateApplication(this.ownerPid);
const windows = NSArray('alloc');
AXUIElementCopyAttributeValues(appRef, kAXWindowsAttribute, 0, 100, windows.ref());

@jackwakefield Sorry to be the bearer of bad news but unfortunately not. This was a while back so I don't remember very well now, but I do remember looking into it for quite some time and coming to the conclusion that I'd need to use something else than NodObjC.

I ended up writing a script in Objective-C, spawning a child process in my electron app, and using stdin / stdout to communicate back and forth between the app & the child process 🙈

Super hacky but that was acceptable for my project. If you want a proper solution you'll likely have to develop a node addon.