tags:

views:

804

answers:

2

I would like to find the window ID of my SWT program.

I start up my SWT shell in the standard way. How do I then find the ID of the window that's been created? The program is executing on Fedora 10 using the Compiz-Fusion window manager (if that makes a difference).

Code to help explain what I mean:

public static void main(String[] args) {
  Display display = new Display();
  Shell shell = new Shell();

  // find window ID here??

  shell.open();

  while (!shell.isDisposed()) {
    if(!display.readAndDispatch()) {
      display.sleep();
    }
  }
}

Update 6 Mar 2009 After looking at and trying out a whole range of things (thanks to VonC for the suggestions below), I came across something that's worked so far. It's supremely dodgy but at least allows me to get on with some other work for the moment.

The ID returned from Control.embeddedHandle is close to the window ID. It's different by a predictable offset. So my code is:

public static void main(String[] args) {
  ...
  Shell shell = new shell(display, SWT.NONE);

  Composite e = new Composite(shell, SWT.EMBEDDED);
  long windowID = e.embeddedHandle - WINDOW_ID_MAGIC_NUMBER;
  e.dispose();
  ....

WINDOW_ID_MAGIC_NUMBER is 5+(number of widgets added to shell before the embedded composite).

It seems reliable on my system so far. I have yet to see if it falls over in a different environment.

+1  A: 

If you create a Composite with the style SWT.EMBEDDED style, then under SWT/GTK+ Composite.embeddedHandle will be an X window ID you can use for parenting an XEMBED child.

Composite embed = new Composite(shell, SWT.EMBEDDED);
System.out.println ("X window ID: " + embed.embeddedHandle);
int hwndChild = OS.GetWindow ( c.handle, OS.GW_CHILD);

This supports embedding using the XEMBED protocol.

This is similar to the JNI code used to get the window ID from its handle

GtkWidget *widget = (GtkWidget *) handle;
GdkWindow *window = widget->window;
xwinid = GDK_WINDOW_XWINDOW(window);

Example of code here.

Example of class using OS:

org.eclipse.swt.widgets.Tree, org.eclipse.swt.widgets.CoolItem,

OS I can find is indeed org.eclipse.swt.internal.win32.OS, not gtk, and it is not a perfect solution because you would access an internal package, but that can give you an idea where to look.

In your case, org.eclipse.swt.internal.gtk.OS is the right class, and you should look in Tree or CoolItem sources how they are using the GetWindow function.
Some other function need to be called in GTK, like may be gtk_container_get_children(int container);

It is said in an answer to the message I was referring at the beginning

If you need the X window, there's no way to do this from the public SWT API (even going through internals), and furthermore even if there was a way I don't think you could guarantee it for all controls. I'm not sure if this works but the closest you could get might be to:

  1. make Control.fixedHandle public
  2. Use OS.GTK_WIDGET_WINDOW (control.fixedHandle) to get a GdkWindow
  3. Use OS.gdk_x11_drawable_get_xid (gdkWindow) to translate that to an X window

I guess the other way might be to take Control.handle, and then call GTK_WIDGET_WINDOW() on it, or if that's null keep calling it on its parents until you find one with a GdkWindow, and then translate that to an X window.

The difficulty here is that SWT talks to GTK+, which talks to GDK, which then talks to X. So, there's three layers between you and the X window.

VonC
Thanks for the help. However, I can't find the GetWindow method or the GW_CHILD property in org.eclipse.swt.internal.gtk.OS - is that the right package to use?
cursa
A: 

Thank you, this helped me great. I've an embedded SWT canvas to show videos with mplayer.

I found another example where the Canvas was created as a SWT control. I could see the field embeddedHandle when debugging, but couldn't access/use it.

According to your example I changed from SWT Control to Composite, and now I can access the embeddedHandle, and it works!