Fork me on GitHub
#interop
<
2022-04-06
>
Nundrum18:04:14

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

Nundrum18:04:52

Here's my attempt at it:

Nundrum18:04:13

(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)18:04:53

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)18:04:27

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

Nundrum18:04:05

that was it, thanks!

Nundrum18:04:53

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)19:04:30

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

Alex Miller (Clojure team)19:04:26

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

Alex Miller (Clojure team)19:04:21

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)19:04:56

I guess you're not even seeing the field though

Alex Miller (Clojure team)19:04:26

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

Nundrum19:04:54

It looks like the difference between getField and getDeclaredField

Nundrum19:04:44

working through it, I think... heh

Alex Miller (Clojure team)19:04:54

Oh yeah you want declared here

Nundrum19:04:19

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

Nundrum19:04:23

Got it! Thanks again.