tags:

views:

265

answers:

4

Specifically, I want to be able to render to an X Window given just its id.

In this case I have a window created in python by gtk.

I can get the window ID of a gtk.Drawable and pass it into my C python module, but can I then make OpenGL calls render to it?

I am aware of gtkglext, but would rather not use it if possible.

Thanks in advance.

A: 
DaedalusFall
Shouldn't you just be using gtk.window.id for glXMakeCurrent? (Caveats I wrote about in answer notwithstanding). It sounds like when you create a widget gtk.window.id is for that widget, so the parent is the window you want. If you don't create the widget then gtk.window.id is the actual window, and the parent is the root window (covering whole screen), thus giving the behaviour you describe.
Nathan Kidd
Yeah I guess so, now that I've seen your answer. I have found a way to get gtk to manage a window that was created manually using XCreateWindow, but the Window decorations won't be drawn until you start swapping the gl buffers, which seems odd.
DaedalusFall
+1  A: 

You don't need to create a new window, you pass an existing window to glXMakeCurrent().
In your current setup you'd need to:

  1. XGetWindowAttributes() to retrieve the visual the window was created with
  2. glXCreateContext() using this visual
  3. glXMakeCurrent() using this context and the window id

However, this is doing it backwards, forcing OpenGL to use the visual used for CreateWindow. This often works because the default visual has sane GLX properties, but a correct application will glXChooseVisual with desired GLX properties, then use that visual to create the window.

Nathan Kidd
A: 

@Daedalus: "I have found a way to get gtk to manage a window that was created manually using XCreateWindow" ... PLEASE, may you explain a little bit more how to do that? I am searching for some similar snippet but I cannot find anything.. just a rough overview :) THX!

Babele Dunnit
A: 

@babele: This page in the python gtk docs say how to make a gtk window from an existing xid. After that you just have to remeber to keep calling glXSwapBuffers for that window (if it is an opengl buffered window, otherwise it should just work when you use window_foreign_new).

So the process goes:

  1. Create a gtk widget that will contain your OpenGL window (a DrawingArea is a good choice - you can't use eg a label as it won't have its own xid)
  2. Get the widget's gtk.gdk.Window (docs)
  3. Get the xid from the gtk.gdk.Window (call this window W1)
  4. Pass it to your C/C++ code
  5. Create the opengl capable window (W2) as a child of W1
  6. Pass the xid of W2 back to python
  7. Use window_foreign_new with W2's xid to create the new gtk.gdk.window object
  8. Each time you call glXSwapBuffers on W2 gtk should then be able to react to expose events.

One bit that really threw me is that if W2 covers the whole of W1 then W1 won't receive events until W2's buffers get swapped. This is particularly confusing if W1 is a top-level window as it can be that nothing appears on your screen at all (the window is there but it looks like whatever is behind it until it gets painted to, which won't happen until it gets an expose event).

Also note that you'll have to manually manage the resizing of W2 by connecting to the gtk resize events. You can do this by connecting to this signal, then calling this function in the handler and passing the results to your c/c++ module where you can resize W2 appropriately. Its a good idea to request a minimum size.

Hope that helps.

DaedalusFall