bringing the panda window on top

Here is my problem. I have a panda window and several pygtk windows in my program ( screenshot : picasaweb.google.co.uk/morel.jer … 4174053058 ). I want that when I click on one of the windows, all other windows are brought to the front. With pygtk it is pretty easy, but I don’t know how to do this with the panda window.

I need a method to bring the panda window on top. Here is what I do :

def bringToFront(self):
        """
        Callback to the 'bringToFront' event.
        """
        print "bringToFront callback"
        # get the window properties
        windowProperties = base.win.getProperties()
        # set the window properties to 'stick on top'
        windowProperties.setZOrder(windowProperties.ZTop)
        base.win.requestProperties(windowProperties)
        # set the window properties to 'normal'
        #windowProperties.setZOrder(windowProperties.ZNormal)
        windowProperties.clearZOrder()
        base.win.requestProperties(windowProperties)

The setOrder(ZTop) works fine, but the clear order doesn’t. The window therefore sticks on top.

You can see that there is a setZOrder(Znormal) commented. I tried it and it doesn’t do what I want either : the ZTop is never done. It just like I did nothing.

And I have an other small question : is there a signal sent when the panda window gets the focus ?

The request is not processed immediately; it is saved until the next frame, or until the next call to base.graphicsEngine.openWindows().

Therefore, call base.graphicsEngine.openWindows() after you have requested ZTop, but before you request ZNormal.

David

Thanks, it half-works :slight_smile:

Here is my new code :

# get the window properties
windowProperties = base.win.getProperties()
# set the window properties to 'stick on top'
windowProperties.setZOrder(windowProperties.ZTop)
base.win.requestProperties(windowProperties)
base.graphicsEngine.openWindows()
# set the window properties to 'normal'
windowProperties.setZOrder(windowProperties.ZNormal)
#windowProperties.clearZOrder()
base.win.requestProperties(windowProperties)

It does goes on top, but it seems that Znormal is not applied for it sticks ont top.

I just saw that there is this warning appearing from time to time :

:display:windisplay(warning): SetForegroundWindow() failed!

That warning isn’t related, I think; it refers to Windows’ enforcement of the rule that an application can’t bring a window to the top unless it is already considered the foreground application. But making a window stick-to-top is, I think, a loophole around that rule.

I think the fact that setting ZNormal doesn’t clear the stick-to-top state is a bug, which has been fixed recently. I understand a new Panda release, 1.4.0, will be out very soon; when it is released, try it in that version and we’ll see if it’s fixed there.

Incidentally, you shouldn’t start with base.win.getProperties(). That returns the complete current properties of the window, but in order to make a request, you are requesting a delta, not a complete properties set. Instead, you should just create an empty WindowProperties, with:

windowProperties = WindowProperties()

David

Ok, thanks, I’ll try this new version as soon as it is released.

Any idea about my other question concerning signals ?

Oh, sorry. Yes, just listen for the event “window-event”.

David

Thanks !

I also want to get the size and position of the window just before it is destroyed (or closed) so that I can save it, but it seems that the window-event is not going to help me with that since I have no way of knowing whether the event was sent due to a “close” event or not.

Any idea about that ?

Sure it will. The window-event passes a WindowProperties structure to your event handling function. You can examine that to determine properties of the window, including size and position; and if properties.getOpen() is false, the window was just closed.

David

Here is what I do :

self.accept('window-event', self.windowEvent)
def windowEvent(self,window):
        """
        This is a special callback.
        It is called when the panda window is modified.
        """
        wp = window.getProperties()
        print "open: ",wp.getOpen()
        print "size: ", wp.getXSize(), wp.getYSize()
        print "pos: ", wp.getXOrigin(), wp.getYOrigin()

The problem is, when I close the window using the close button, no event seems to be catched.

If you look in ShowBase.py in the source, you see that the window-event is already catched by ShowBase itself – I dont know if that forms a problem?

But to catch an application close, you could do one of the following:

  1. catch the SystemExit exception,
    or 2. use python’s atexit module to register a function which is called on application close. Like this:
import atexit
def myExitFunc():
  print "Goodbye!"
atexit.register(myExitFunc)
#the rest of your program here

But this doesnt work on multiple windows.

If I use atexit, I can’t get the window size and position, unless I stored them in variables before. This can be done, but that’s not exactly what I wanted to do.

If you close the main window, the ShowBase code will receive the window event and exit the application, possibly before your own event handler gets a chance to be called. Is that what’s causing you problems?

There are two workarounds. One is to reassign base.win to None, so that ShowBase will no longer believe that the open window is the “main” window, and won’t automatically close the application. The other is to change the default window event to some other string that ShowBase is not listening for, like this:

base.win.setWindowEvent('my-window-event')

Then you hang a hook on my-window-event instead of window-event.

David

Thansk drwr, it works great.

I used the second workaround for I need base.win almost everywhere. And it seems more elegant to me too.