-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added a (very) basic tree walking functionality for Mac #49
Changes from all commits
0484cc8
616df5c
afdcfdd
b7242e3
c90c056
59352f7
6ee2972
a1b2ef4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,36 @@ | ||
#ifndef LIB_MAC_AXAPI_NODE_H_ | ||
#define LIB_MAC_AXAPI_NODE_H_ | ||
|
||
#include <ApplicationServices/ApplicationServices.h> | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace mac_inspect { | ||
|
||
class AXAPINode; | ||
typedef std::unique_ptr<AXAPINode> AXAPINodePtr; | ||
|
||
class AXAPINode { | ||
public: | ||
explicit AXAPINode(AXUIElementRef ax_element); | ||
~AXAPINode() = default; | ||
|
||
static AXAPINode createForPID(long pid); | ||
static AXAPINodePtr createForPID(long pid); | ||
|
||
std::string GetRole(); | ||
std::string GetTitle(); | ||
std::vector<std::string> GetAttributeNames(); | ||
std::string GetStringAttributeValue(std::string& attribute_name); | ||
long GetChildCount(); | ||
AXAPINodePtr GetChildAt(long index); | ||
|
||
private: | ||
AXUIElementRef ax_element_; | ||
explicit AXAPINode(AXUIElementRef ax_element); | ||
AXUIElementRef ax_ui_element_; | ||
}; | ||
|
||
} // namespace mac_inspect | ||
|
||
#endif // LIB_MAC_AXAPI_NODE_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,30 +11,43 @@ | |
if (cf_string == nullptr) | ||
return ""; | ||
|
||
const char* chars = CFStringGetCStringPtr(cf_string, CFStringGetSystemEncoding()); | ||
const char* chars = | ||
CFStringGetCStringPtr(cf_string, CFStringGetSystemEncoding()); | ||
if (!chars) { | ||
// CFStringRef can secretly be an NSString, in which case CFStringGetCStringPtr doesn't work. | ||
NSString* ns_string = (__bridge NSString*) cf_string; | ||
const char* ns_chars = [ns_string cStringUsingEncoding:[NSString defaultCStringEncoding]]; | ||
// CFStringRef can secretly be an NSString, in which case | ||
// CFStringGetCStringPtr doesn't work. | ||
NSString* ns_string = (__bridge NSString*)cf_string; | ||
const char* ns_chars = | ||
[ns_string cStringUsingEncoding:[NSString defaultCStringEncoding]]; | ||
chars = ns_chars ? ns_chars : ""; | ||
} | ||
return std::string(chars); | ||
} | ||
|
||
AXAPINode::AXAPINode(AXUIElementRef ax_element) : ax_element_(ax_element) {} | ||
AXAPINode::AXAPINode(AXUIElementRef ax_ui_element) | ||
: ax_ui_element_(ax_ui_element) {} | ||
|
||
AXAPINodePtr AXAPINode::createForPID(long pid) { | ||
AXUIElementRef ax_ui_element = AXUIElementCreateApplication((pid_t)pid); | ||
return std::unique_ptr<AXAPINode>(new AXAPINode(ax_ui_element)); | ||
} | ||
|
||
std::string AXAPINode::GetRole() { | ||
CFTypeRef cf_role = nullptr; | ||
if (AXUIElementCopyAttributeValue(ax_element_, kAXRoleAttribute, &cf_role) != noErr) | ||
if (AXUIElementCopyAttributeValue(ax_ui_element_, kAXRoleAttribute, | ||
&cf_role) != kAXErrorSuccess) { | ||
return ""; | ||
} | ||
|
||
return CFStringRefToStdString((CFStringRef) cf_role); | ||
return CFStringRefToStdString((CFStringRef)cf_role); | ||
} | ||
|
||
std::string AXAPINode::GetTitle() { | ||
CFStringRef cf_title = nullptr; | ||
if (AXUIElementCopyAttributeValue(ax_element_, kAXTitleAttribute, (CFTypeRef*)&cf_title) != noErr) | ||
if (AXUIElementCopyAttributeValue(ax_ui_element_, kAXTitleAttribute, | ||
(CFTypeRef*)&cf_title) != kAXErrorSuccess) { | ||
return ""; | ||
} | ||
|
||
return CFStringRefToStdString(cf_title); | ||
} | ||
|
@@ -48,9 +61,28 @@ | |
return ""; | ||
} | ||
|
||
AXAPINode AXAPINode::createForPID(long pid) { | ||
AXUIElementRef axuielement = AXUIElementCreateApplication((pid_t) pid); | ||
return AXAPINode(axuielement); | ||
long AXAPINode::GetChildCount() { | ||
CFArrayRef children_ref; | ||
if ((AXUIElementCopyAttributeValue(ax_ui_element_, kAXChildrenAttribute, | ||
(CFTypeRef*)&children_ref)) != | ||
kAXErrorSuccess) { | ||
return 0; | ||
} | ||
return CFArrayGetCount(children_ref); | ||
} | ||
|
||
AXAPINodePtr AXAPINode::GetChildAt(long index) { | ||
CFArrayRef children_ref; | ||
if ((AXUIElementCopyAttributeValue(ax_ui_element_, kAXChildrenAttribute, | ||
(CFTypeRef*)&children_ref)) != | ||
kAXErrorSuccess) { | ||
return nullptr; | ||
} | ||
AXUIElementRef child_ref = | ||
(AXUIElementRef)CFArrayGetValueAtIndex(children_ref, index); | ||
if (!child_ref) | ||
return nullptr; | ||
return AXAPINodePtr(new AXAPINode(child_ref)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I think all of these helper functions, ultimately, might only be implemented in AxapiNodeImpl, like the AtspiNodeImpl: https://github.com/Igalia/AXAccess/pull/43/files#diff-3d31a27d5b501604330a8b1dd58434d1a6848428ec6b28afdefc85002e1e439b And ultimately a goal for the test suite is to surface I wonder if the next step is to for you to copy the outline presented in Edu's PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I wonder if "GetChildCount" and "GetChildAt" are the right abstractions for the "cross platform" part of the API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah, makes sense!
Yeah, once that change lands I can work on making the Mac version of
Yeah, good question. Do you think potentially returning a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It just seems to make more sense from a scripting language perspective. We can change it at a future time! |
||
} | ||
|
||
} // namespace mac_inspect |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
%module mac_inspect | ||
|
||
%{ | ||
#include <axaccess/mac/axapi_node.h> | ||
%} | ||
|
||
|
||
%include "std_string.i" | ||
%include <std_unique_ptr.i> | ||
%unique_ptr(AXAPINode) | ||
%unique_ptr(mac_inspect::AXAPINode) | ||
|
||
%include <axaccess/mac/axapi_node.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious the motivation for this name change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making it match the platform type name more closely, because I was confusing myself :)