interop 2022-04-06

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(); }

Here's my attempt at it:

(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

that was it, thanks!

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

It looks like the difference between getField and getDeclaredField

working through it, I think... heh

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

Oh yeah you want declared here

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

Got it! Thanks again.