interop

Nundrum 2022-04-06T18:01:44.664109Z

I'm trying to do this code in Clojure: https://github.com/robbieh/AWTForeignXWindow/blob/main/src/main/java/nundrum/net/TryReflect.java

Nundrum 2022-04-06T18:02:14.514189Z

Frame frame = new Frame("test");

		frame.setVisible(true);
		frame.setVisible(false);

		ComponentAccessor acc = AWTAccessor.getComponentAccessor();

		ComponentPeer peer = acc.getPeer(frame);

		Class pc = peer.getClass();
		try {
			Method gs = pc.getMethod("getShell",null); gs.setAccessible(true);
			Object o = gs.invoke(peer);
			out.format("Got ID %d", (long) o);
		} 
		catch (NoSuchMethodException x) { x.printStackTrace(); }
		catch (IllegalAccessException x) { x.printStackTrace(); }
		catch (InvocationTargetException x) { x.printStackTrace(); }

Nundrum 2022-04-06T18:04:52.813819Z

Here's my attempt at it:

Nundrum 2022-04-06T18:05:13.073179Z

(def f (new Frame "AWT test"))
  (. f setSize 400 400)
  (. f setLayout (new GridLayout 3 1))
  (class f)     ;;java.awt.Frame
  (supers (class f));; #{java.awt.Container java.io.Serializable java.awt.Window java.awt.image.ImageObserver java.awt.Component java.awt.MenuContainer java.lang.Object javax.accessibility.Accessible}
    (r/reflect (.getAccessibleContext f) )
    
  (def acc (AWTAccessor/getComponentAccessor))
  (.getBounds acc f);; #object[java.awt.Rectangle 0x40af415a "java.awt.Rectangle[x=1280,y=0,width=400,height=400]"]
  (def peer (.getPeer acc f) )
  (class peer);; sun.awt.X11.XFramePeer
  
  (def pc (.getClass peer))
  (def gsm  (.getMethod pc "getShell" nil) );; #object[java.lang.reflect.Method 0x45a836a "public long sun.awt.X11.XDecoratedPeer.getShell()"]

   (.invoke gsm peer)
   ;;Execution error (IllegalArgumentException) at jnatest.core/eval9293 (form-init8734797063564353548.clj:157).
   ;;No matching method invoke found taking 1 args for class java.lang.reflect.Method
   ;;Clojure: class java.lang.IllegalArgumentException

Alex Miller (Clojure team) 2022-04-06T18:07:53.024859Z

I suspect (def gsm (.getMethod pc "getShell" nil) ) - that nil there should be an empty Class array (into-array Class [])

💥 1
Alex Miller (Clojure team) 2022-04-06T18:08:27.434639Z

and then on the invoke, should be an Object array of the peer

Nundrum 2022-04-06T18:11:05.896309Z

that was it, thanks!

Nundrum 2022-04-06T18:29:53.859659Z

So there's a state field on this object. https://github.com/openjdk/client/blob/master/src/java.desktop/unix/classes/sun/awt/X11/XFramePeer.java#L47

(.getField pc "state")
;;Clojure: class java.lang.NoSuchFieldException
Is there something as obviously wrong there?

Alex Miller (Clojure team) 2022-04-06T19:32:30.128969Z

well that class isn't public so that won't be accessible via reflection

Alex Miller (Clojure team) 2022-04-06T19:33:26.927679Z

it is possible (under some constraints) to make it accessible by calling (.setAccessible field true)

Alex Miller (Clojure team) 2022-04-06T19:34:21.501809Z

that's subject to the Java security policy, and support has changed several times over the JDK's lifetime, and in Java 9+ you probably start to run into module visibility issues

Alex Miller (Clojure team) 2022-04-06T19:34:30.779809Z

but it might work! :)

Alex Miller (Clojure team) 2022-04-06T19:34:56.620509Z

I guess you're not even seeing the field though

Alex Miller (Clojure team) 2022-04-06T19:35:26.773479Z

which Java version are you on? they've really started locking these sun classes down hard as of Java 16

Nundrum 2022-04-06T19:43:54.011569Z

It looks like the difference between getField and getDeclaredField

Nundrum 2022-04-06T19:44:44.190789Z

working through it, I think... heh

Alex Miller (Clojure team) 2022-04-06T19:47:54.387959Z

Oh yeah you want declared here

Nundrum 2022-04-06T19:53:19.772209Z

(def xbw (Class/forName "sun.awt.X11.XBaseWindow"))
 (.getDeclaredField xbw "window")

Nundrum 2022-04-06T19:53:23.636219Z

Got it! Thanks again.