Search code examples
swinguser-interfacejava-native-interfacexservermotif

Make JVM dialog a child window of native top-level window


I have a legacy, X/Motif, C++ application for which new windows have been added using Java/JNI.

New Java windows have been either top level windows or dialogs with no parent.

Is there any reasonable way to get a child window created by the JVM, such as a JDialog, to have as its parent a window created on the native side using X/Motif, and if yes then how? This would still be useful even if Java AWT/Swing is not aware of the parenting structure and the window manager just kept the dialog on top of the top-level window (of course, having all the normal control over windows in Java would be preferable, just not strictly necessary for all uses of my question).

I am thinking the answer might be "No, not in any reasonable way. You would have to do epic surgery on both your native side and within the JVM." If that is the answer, then so be it. But I am hoping someone has an answer along the lines of "If you make this X call or that window manager call, you can get the window manager to supply certain dialog properties with the argument top-level window as the parent."

Essentially, I am looking to increase the integration between the C++ and Java user interfaces as much as possible. Right now, they are run as one application by using JNI, but the GUI windows/components are essentially separate, despite sharing data.

One benefit of this, already mentioned, is having dialogs not show up behind what the user perceives as the top level window.

Another thing I have considered, though I probably will not do (tell me how crazy you think it is), is to make it appear as though Java components are in the C++ window by getting the screen coordinates of a component on the C++ side, displaying a borderless window on the Java side at that screen location, so it looks like it's part of the C++ application. I can think of so many negative side effects of this, though, that I would not do it unless there was a simple way to negate them (focus issues, a window displaying between this dummy window and the real top level window, and other things would affect user experience). Even avoiding this, though, there are still benefits to an affirmative answer to my question.


Solution

  • If you're using the XToolkit (Java 1.7+), you can proceed as follows:

    1. Get the numeric id of the native peer of a java.awt.Window instance (see this answer).
    2. Find the corresponding X11 Window struct by its id by iterating the clients of the X server (see the sources of xwininfo and xlsclients utilities, also Select_Window_Args(int*, char**)).
    3. Use XReparentWindow().