views:

27

answers:

0

With PyGTK running on Windows, I want to have a new window pop up near a parent window, but never off-screen.

I observed the behavior I want in Microsoft Wordpad in both Windows 7 and Windows XP. If you make the window very small and move it to the bottom right of the desktop, right click in the text field, and open the Paragraph menu, the dialog pops up fully visible. This happens even if the Wordpad window is partially off-screen. The child dialog does not pop up in a fixed position relative to the main window. It just pops up close, and fully visible.

My application consists of a main screen which spawns child windows that block the rest of the application until the user is finished using them. The user may have to open and close many child windows in sequence, so I want them to appear near where they click on the button, so the user doesn't have to move the mouse all over the screen.

I tried using *gtk.WIN_POS_MOUSE*, but when the main menu is near an edge of the screen; the child window that spawns often ends up partially off-screen.

I would expect that a call to *set_transient_for(main_menu)* on a child window should inform Windows that I want my window to be near its parent. However, Windows just places it at the top left of the desktop -- not even necessarily on the same screen as the main menu.

The following code will demonstrate the problem by popping up a window at the bottom left of your screen that contains a button which spawns a subwindow when clicked:

import gtk

class MyWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.connect("delete-event",self.on_delete_event)
        button = gtk.Button("Open Subwindow")
        button.connect("clicked",self.open_sub_window)
        self.add(button)
        self.set_gravity(gtk.gdk.GRAVITY_SOUTH_EAST)
        self.show_all()
        width, height = self.get_size()
        self.move(gtk.gdk.screen_width() - width, gtk.gdk.screen_height() - height)

    def on_delete_event(self, widget=None, data=None):
        gtk.main_quit()

    def open_sub_window(self, widget=None, data=None):
        w = gtk.Window()
        w.set_size_request(200,200)
        w.set_transient_for(self)
        w.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
        w.show()

if __name__=="__main__":
    MyWindow()
    gtk.main()

As you can see, the sub_window shows up partially off-screen. If you comment out the line *w.set_position(gtk.WIN_POS_CENTER_ON_PARENT)* you will see that the Windows window manager just places the subwindow at the very top left of the desktop. Not very useful!

Is there a way to get the desired behavior without resorting to manually managing Window positioning by checking what location the window ends up at and then moving the window to a fully off-screen position?