toplevel .t1
toplevel .t2
grab .t2
wm transient .t2 .t1
focus -force .t2
Now, if you click on the main toplevel (the one titled "Wish84"), the
click is ignored, the titlebar remains grayed. This is correct, as
there is an active grab.
Then, click on the icon corresponding to "Wish84" in the windows
taskbar. The toplevel becomes active (i.e. its title bar becomes blue,
and goes to the front of the z order, although it ignores keyboard and
mouse). This is inconsistent. Furthermore, no Activate nor FocusIn
events are fired.
This is causing a serious problem to some users: just imagine that in
the previous scenario "Wish84" hides the window that has the grab; the
user ends with a unresponsive toplevel and no clue about how to regain
control of the application (a solution is to click the taskbar entries
of other toplevels of the application until the one that has the grab
becomes active).
As mentioned, no events are fired, so the application can do nothing
to prevent this mess.
Any ideas how to correct this?
--
Oscar
wm attributes .t2 -topmost 1
I'm not under Windows right now, so I'm not sure this will do the trick.
<Quote>
If you're writing code to create a transient window, you should either:
* wait until your toplevel is mapped, then make it transient, then
withdraw and deiconify, OR
* create your toplevel, withdraw it, update idletasks, mark as
transient, and then deiconify.
I favour the second approach, as follows:
toplevel .t
wm withdraw .t
update idletasks
wm transient .t .
wm deiconify .t
</Quote>
Taking a look at wiki.tcl.tk usually helps...
> I just find some lines on the wiki (http://wiki.tcl.tk/3542) that
> might also help you:
>
> <Quote>
> If you're writing code to create a transient window, you should either:
>
> * wait until your toplevel is mapped, then make it transient, then
> withdraw and deiconify, OR
> * create your toplevel, withdraw it, update idletasks, mark as
> transient, and then deiconify.
>
> I favour the second approach, as follows:
>
> toplevel .t
> wm withdraw .t
> update idletasks
> wm transient .t .
> wm deiconify .t
> </Quote>
>
> Taking a look at wiki.tcl.tk usually helps...
Hi Simon.
I'll study in detail the wiki page you mentioned, but your code does
not solve the problem, nor does the "wm .t -topmost 1" trick, which
only adds the inconvenience of putting the toplevel in front of all
other windows, but still allows activating them.
Thanks four your attention.
--
Oscar
> I'll study in detail the wiki page you mentioned, but your code does
> not solve the problem, nor does the "wm .t -topmost 1" trick, which
> only adds the inconvenience of putting the toplevel in front of all
> other windows, but still allows activating them.
I thought that that was exatly what you wanted: avoid that the toplevel
that has the grab gets hidden by the others (just to make sure you
understood my suggestion right: it should be "wm .t2 -topmost 1" in your
example...).
AFAIK you can't avoid that a window gets "activated" when you click its
titlebar or its icon in the taskbar. This is because the grab is set at
"Tk level" and not at "Window manager level" (at least, that's what I
understood from the "grab" manpage): if you click the "main" toplevel in
the taskbar it's the window manager that gets the event and since it
does not know nothing about the grab, it "activates" the window. However
the window then is not truly active, since all events seen by the app
(what happen inside) are still sent to the toplevel that has the grab.
I realized that I probably did not understand you right in first place:
you have actually three toplevels: "main" ('.'), '.t1' and '.t2' (which
should remain above the others and get all events). And it's '.' that
causes the problem that it might hide '.t2', right?
In that case the solution is easy: just make '.t1' transient towards '.' :
wm transient .t2 .t1
wm transient .t1 .
As said, the toplevels that don't have the grab will still become
"active" if you click them in the taskbar, but they will no longer hide
'.t2'.
Once the grab removed (or .t2 unmapped) you might want .t1 no longer be
transient:
wm transient .t1 {}
Hope this helps
Simon
> I thought that that was exatly what you wanted: avoid that the
> toplevel that has the grab gets hidden by the others (just to make
> sure you understood my suggestion right: it should be "wm .t2 -topmost
> 1" in your example...).
Yeah, but it will stand in front of all other applications'
windows. This is not good. A "local topmost" would be a good interim
solution, but AFAIK this is not possible with Tk.
> AFAIK you can't avoid that a window gets "activated" when you click
> its titlebar or its icon in the taskbar.
Part of the problem comes from the fact that the window is activated
only when you use the taskbar. If you click directly on the window,
the click is ignored. This is inconsistent. No activation should take
place no matter what the user does.
> This is because the grab is
> set at "Tk level" and not at "Window manager level" (at least, that's
> what I understood from the "grab" manpage): if you click the "main"
> toplevel in the taskbar it's the window manager that gets the event
> and since it does not know nothing about the grab, it "activates" the
> window. However the window then is not truly active, since all events
> seen by the app (what happen inside) are still sent to the toplevel
> that has the grab.
The window is not "truly" active, but the user perceives it as active
as demonstrated for its decoration and the fact that it comes to the
front. This is either a bug on the window manager or in Tk's
implementation of `grab'.
> I realized that I probably did not understand you right in first
> place: you have actually three toplevels: "main" ('.'), '.t1' and
> .t2' (which should remain above the others and get all events). And
> it's '.' that causes the problem that it might hide '.t2', right?
> In that case the solution is easy: just make '.t1' transient towards '.' :
>
> wm transient .t2 .t1
> wm transient .t1 .
Sadly, my problem is more general. There are an arbitrary number of
toplevels and any of them can bring a dialog any time. Your proposal
solves the case where the user clicks on the taskbar icon of ".", but
not for the other toplevels.
As a side note, showing a tk_messageBox with -parent set to any
toplevel should be enough to demonstrate the problem. However, they
use the "topmost" trick, which demonstrates that the problem was known
to some Tk developers.
[snip]
> Hope this helps
Thanks for your analysis, Simon. I'll look at Tk's source and see how
`grab' is implemented, and then, maybe, file a bug report.
--
Oscar