logo       
Bookmark and Share

Re: behaviour of window.present() on different WM: msg#00046

gnome.gtk+.python

Subject: Re: behaviour of window.present() on different WM

On Thu, 9 Dec 2004 22:18:18 +0100, Gian Mario Tagliaretti
<g.tagliaretti@xxxxxxxxxxxxxxxx> wrote:

<snip>

> def newTree(self, widget, event):
> self.win2 = gtk.Window(gtk.WINDOW_TOPLEVEL)
> self.win2.set_default_size(300, 300)
> self.tree = gtk.TreeView()
> self.win2.add(self.tree)
> self.win2.show_all()
> self.win.grab_focus()
> self.win.present()

Short answer: I belive that you should use
self.win2.set_focus_on_map(gtk.FALSE) before showing it and remove the
calls you used to focus self.win.

Problem with short answer: This is the correct way for X window
managers, but not all support the _NET_WM_USER_TIME property in the
EWMH spec of freedesktop.org yet. (Metacity has support in the 2.8.x
releases with x>=5, but it was disabled because some libraries and
apps don't have sufficient support--so you'll actually have to wait
for Gnome 2.10 for Metacity support...). So, this probably still
won't work today for you, but other than some hack to force self.win2
to be mapped (and not just queued for mapping) before calling
self.win.present() I don't see any way to currently get the behavior
you want consistently.

Long answer:
This looks like a race condition to me. I don't know how Windows
works, so let me just assume you're on an X server.
self.win2.show_all() tells gtk to show the window, which then has gtk+
do a bunch of stuff to tell X to map the window. But, of course, X is
asynchronous and it gets around to mapping it when it wants to...

You then call self.win.present, to try to make sure self.win is
focused instead of self.win2. This also ends up in a gtk+ call that
results in an X client message to the window manager.

Now, the window manager is (probably) going to focus self.win when it
gets the Xclient message generated from your self.win.present() call,
and is (probably) going to focus self.win2 when it receives the
mapping notification for that window. However, the order in which
those two events are received is non-deterministic. (I say probably
in both cases because the window manager is free to do just about
whatever it wants in most circumstances, even without violating the
EWMH spec)

Those events are sent from gtk+ with a timestamp (assuming a
sufficiently recent version of gtk+) but unfortunately they'll both be
sent with the timestamp of gtk_get_current_event_time so the window
manager will be unable to distinguish the present() call as having
come later.

> self.win2.set_keep_above(gtk.TRUE)

Why are you setting the ABOVE state? I believe what you want to do is
to self.win2.set_transient_for(self.win) -- that doesn't have the
nasty side-effects of keep_above (which, the gtk+ documentation aptly
states that app authors should avoid).

> After I spoke with xordoquy (thanks again) in IRC he proposed this:
>
> def newTree(self, widget, event):
> self.win2 = gtk.Window(gtk.WINDOW_TOPLEVEL)
> self.win2.set_default_size(300, 300)
> self.tree = gtk.TreeView()
> self.win2.add(self.tree)
> self.win2.show_all()
> gtk.idle_add(self.delay)
>
> def delay(self):
> self.win.present()
> self.win.grab_focus()
> self.win2.set_keep_above(gtk.TRUE)

This is basically an attempt to avoid the race condition by adding a
timing separation between the self.win2.show_all() and the
self.win.present(). It doesn't look very failproof...

> It does work only once (the first time you press a button but then not
> anymore) on gnome (metacity), with fluxbox it doesn't work at all.

Another question is whether fluxbox supports _NET_ACTIVE_WINDOW (since
gtk_window_present is implemented by sending that X client message...)



Hope that helps,
Elijah
_______________________________________________
pygtk mailing list pygtk@xxxxxxxxxx
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/



<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | Mail Home | sitemap | FAQ | advertise