Like this nested type of property, how should I write its structure?

10 views
Skip to first unread message

Hank Huang

unread,
Jul 6, 2021, 10:41:52 AM7/6/21
to Java Native Access
WechatIMG291.png

WechatIMG290.png

Daniel B. Widdis

unread,
Jul 6, 2021, 12:29:43 PM7/6/21
to Java Native Access
First, some feedback.  It's difficult to review screenshots in my email client and it's harder to guess what  you're trying to do.

Secondly I didn't see the question for a while because it's in the subject line.  It would be more helpful to readers ask the question in the body of the email.

It looks like you want to map AXUIElementRef.  For that you need to go to either the documentation or the header file.

A brief web search shows the documentation here: AXUIElementRef | Apple Developer Documentation
That matches the header file declaration: WebCoreSystemInterface.h (apple.com) 

Both appear to be pointers so you could simply extend PointerType to decorate it for type safety.  However, the documentation for AXUIElement, which the reference points to, is here:  AXUIElement.h | Apple Developer Documentation

The overview on that page indicates it's an extension of CFTypeRef, which is mapped in JNA's CoreFoundation class.  See the mappings for CFNumberRef and CFStringRef, which are declared similarly and have helper methods to provide a more object oriented approach.  jna/CoreFoundation.java at f89905af56aef305d569db5ae1b06607807edcc9 · java-native-access/jna (github.com)




On Tue, Jul 6, 2021 at 7:41 AM 'Hank Huang' via Java Native Access <jna-...@googlegroups.com> wrote:
WechatIMG291.png

WechatIMG290.png

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/367b109f-5341-4466-957d-800f82440583n%40googlegroups.com.


--
Dan Widdis

Hank Huang

unread,
Jul 6, 2021, 8:30:35 PM7/6/21
to jna-...@googlegroups.com
I found the corresponding attribute of AXUIElementRef in http://mirror.informatimago.com/next/developer.apple.com/releasenotes/Accessibility/AssistiveAPI.html. But the Value Type of the attribute of kAXParentAttribute and kAXWindowAttribute is another AXUIElementRef, which makes me unable to start. At the same time I also refer to the mapping of CFStringRef.

From: jna-...@googlegroups.com <jna-...@googlegroups.com> on behalf of Daniel B. Widdis <wid...@gmail.com>
Sent: Wednesday, July 7, 2021 12:29 AM
To: Java Native Access <jna-...@googlegroups.com>
Subject: Re: Like this nested type of property, how should I write its structure?
 
[EXTERNAL]

You received this message because you are subscribed to a topic in the Google Groups "Java Native Access" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jna-users/YlU67Ycb8t0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/CANb1Va6z1gMZxvnijaLvg6AC05Onoyq8aBvBCa7hC1Jd0hPpEA%40mail.gmail.com.

Daniel Widdis

unread,
Jul 6, 2021, 9:13:24 PM7/6/21
to jna-...@googlegroups.com

All of these <something>Ref variables are pointers.  You could probably get away with just mapping everything to a pointer, ant it would work, but it’s better to be type safe.

 

Some of these pointers point to specific things (in this case, an element of a UI like a button or toolbar, etc.) which is why for type safety you should generally do more than just use “Pointer” everywhere.

 

You should probably be able to define this and do most of what you need to if you use the mapping in CoreFoundation:

 

class AXUIElementRef extends CFTypeRef {

}

 

Or you could also do this with core JNA.

 

class AXUIElementRef extends PointerType {

}

 

Let me know what doesn’t work with this simple mapping.

 

From: 'Hank Huang' via Java Native Access <jna-...@googlegroups.com>
Reply-To: <jna-...@googlegroups.com>
Date: Tuesday, July 6, 2021 at 5:30 PM
To: "jna-...@googlegroups.com" <jna-...@googlegroups.com>
Subject: Re: Like this nested type of property, how should I write its structure?

 

I found the corresponding attribute of AXUIElementRef in http://mirror.informatimago.com/next/developer.apple.com/releasenotes/Accessibility/AssistiveAPI.html. But the Value Type of the attribute of kAXParentAttribute and kAXWindowAttribute is another AXUIElementRef, which makes me unable to start. At the same time I also refer to the mapping of CFStringRef.


From: jna-...@googlegroups.com <jna-...@googlegroups.com> on behalf of Daniel B. Widdis <wid...@gmail.com>
Sent: Wednesday, July 7, 2021 12:29 AM
To: Java Native Access <jna-...@googlegroups.com>
Subject: Re: Like this nested type of property, how should I write its structure?

 

[EXTERNAL]

First, some feedback.  It's difficult to review screenshots in my email client and it's harder to guess what  you're trying to do.

 

Secondly I didn't see the question for a while because it's in the subject line.  It would be more helpful to readers ask the question in the body of the email.

 

It looks like you want to map AXUIElementRef.  For that you need to go to either the documentation or the header file.

 

A brief web search shows the documentation here: AXUIElementRef | Apple Developer Documentation

That matches the header file declaration: WebCoreSystemInterface.h (apple.com) 

 

Both appear to be pointers so you could simply extend PointerType to decorate it for type safety.  However, the documentation for AXUIElement, which the reference points to, is here:  AXUIElement.h | Apple Developer Documentation

 

The overview on that page indicates it's an extension of CFTypeRef, which is mapped in JNA's CoreFoundation class.  See the mappings for CFNumberRef and CFStringRef, which are declared similarly and have helper methods to provide a more object oriented approach.  jna/CoreFoundation.java at f89905af56aef305d569db5ae1b06607807edcc9 · java-native-access/jna (github.com)

 

 

 

 

On Tue, Jul 6, 2021 at 7:41 AM 'Hank Huang' via Java Native Access <jna-...@googlegroups.com> wrote:

 

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/367b109f-5341-4466-957d-800f82440583n%40googlegroups.com.


 

--

Dan Widdis

--
You received this message because you are subscribed to a topic in the Google Groups "Java Native Access" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jna-users/YlU67Ycb8t0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/CANb1Va6z1gMZxvnijaLvg6AC05Onoyq8aBvBCa7hC1Jd0hPpEA%40mail.gmail.com.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.

Hank Huang

unread,
Jul 6, 2021, 10:30:55 PM7/6/21
to jna-...@googlegroups.com
public interface ApplicationServices extends Library {
    ApplicationServices INSTANCE = Native.load("ApplicationServices", ApplicationServices.class);
    class AXUIElementRef extends CFTypeRef {
        public AXUIElementRef() {
            super();
        }

        public AXUIElementRef(Pointer p) {
            super(p);
        }
    }
   
    AXUIElementRef AXUIElementCreateApplication(int pid);

    CFBooleanRef AXUIElementCopyAttributeValue(AXUIElementRef element,String attribute,CFBooleanRef value);

}

public static void main(String[] args) {
    ApplicationServices.AXUIElementRef element = ApplicationServices.INSTANCE.AXUIElementCreateApplication(75239);
    System.out.println(ApplicationServices.INSTANCE.AXUIElementCopyAttributeValue(element,"kAXEnabledAttribute", null).booleanValue());
}
I try to call AXUIElementCopyAttributeValue to get the "kAXEnabledAttribute" for element, But it failed.

From: jna-...@googlegroups.com <jna-...@googlegroups.com> on behalf of Daniel Widdis <wid...@gmail.com>
Sent: Wednesday, July 7, 2021 9:13 AM

To: jna-...@googlegroups.com <jna-...@googlegroups.com>
Subject: Re: Like this nested type of property, how should I write its structure?
 
[EXTERNAL]

Hank Huang

unread,
Jul 6, 2021, 10:31:56 PM7/6/21
to jna-...@googlegroups.com

Daniel Widdis

unread,
Jul 7, 2021, 1:03:03 AM7/7/21
to jna-...@googlegroups.com

> I try to call AXUIElementCopyAttributeValue to get the "kAXEnabledAttribute" for element, But it failed.

 

The second argument of AXUIElementCopyAttributeValue is a CFString. You can’t just pass a regular String.

 

Change your attribute parameter to CFString and create one with your String.  (And CFRelease() it when you’re done with it.  The CFString helper methods in JNA’s CoreFoundation class can help with all this.)

Hank Huang

unread,
Jul 7, 2021, 3:09:18 AM7/7/21
to jna-...@googlegroups.com
public class test {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

    public interface ApplicationServices extends Library {
        ApplicationServices INSTANCE = Native.load("ApplicationServices", ApplicationServices.class);
        class AXUIElementRef extends CFTypeRef {
            public AXUIElementRef() {
                super();
            }

            public AXUIElementRef(Pointer p) {
                super(p);
            }
        }

        AXUIElementRef AXUIElementCreateApplication(int pid);

        int AXUIElementCopyAttributeValue(AXUIElementRef element, CFStringRef attribute, CFTypeRef value);

        void AXUIElementPerformAction(AXUIElementRef element,CFStringRef action);


    }

    public static void main(String[] args) {
        CFStringRef attribute = CFStringRef.createCFString("kAXTitleAttribute");
        CFArrayRef value;
        value = new CFArrayRef();
        ApplicationServices.AXUIElementRef element = ApplicationServices.INSTANCE.AXUIElementCreateApplication(75102);
        ApplicationServices.INSTANCE.AXUIElementCopyAttributeValue(element,attribute,value);
        System.out.println("value = " + value);
        attribute.release();
//        ApplicationServices.INSTANCE.AXUIElementPerformAction(element,CFStringRef.createCFString("kAXPressAction"));
    }
}

/// return value = NULL
I tried to do this, but the return value it gave me was just null and I make sure my pid is correct

Sent: Wednesday, July 7, 2021 1:02 PM

To: jna-...@googlegroups.com <jna-...@googlegroups.com>
Subject: Re: Like this nested type of property, how should I write its structure?
 
[EXTERNAL]

Daniel B. Widdis

unread,
Jul 7, 2021, 3:18:26 PM7/7/21
to Java Native Access
1. What is the return value for the call to AXUIElementCopyAttributeValue?  It should give you a hint as to what's wrong.

2. I think you have incorrectly mapped the value variable.  It is a pointer to a CFTypeRef, not the CFTypeRef reference itself.  

You should map the third argument as a PointerByReference, then instantiate a new CFTypeRef from the pointed-to value.  (Here is where if you are absolutely certain it's an array ref, you can skip straight to that.)

Function mapping:
int AXUIElementCopyAttributeValue(AXUIElementRef element, CFStringRef attribute, PointerByReference valuePtr);

Use in code:
PointerByReference valuePtr = new PointerByReference(); 
ApplicationServices.INSTANCE.AXUIElementCopyAttributeValue(element,attribute,valuePtr);
CFArrayRef value = new CFArrayRef(valuePtr.getValue()); // throws ClassCastException if not the correct type






--
Dan Widdis

Daniel B. Widdis

unread,
Jul 7, 2021, 3:36:48 PM7/7/21
to Java Native Access
Another note, you need to release the "element" reference at the end of your code as well.

Any time you use methods with "Create" or "Copy" in the name which produce these CFTypeRef pointers, they must later be released.  It's generally a good practice to use try/finally blocks to release even if you encounter exceptions inside the code.

ApplicationServices.AXUIElementRef element = ApplicationServices.INSTANCE.AXUIElementCreateApplication(75102);
if (element != null) {
    try {
        // your code here
    } finally {
        element.release();
    }
}









--
Dan Widdis

Hank Huang

unread,
Jul 8, 2021, 4:12:37 AM7/8/21
to jna-...@googlegroups.com
I'm very much obliged to you! This works for me!!!!!

2021年7月8日 上午3:36,Daniel B. Widdis <wid...@gmail.com> 写道:

[EXTERNAL]

[EXTERNAL]

[EXTERNAL]

<image001.png>

 

<image002.png>

Reply all
Reply to author
Forward
0 new messages