Tk Source Code

View Ticket
Login
Ticket UUID: ee3361a3ad36260b4eedbbf3fa920bf38b570c1
Title: Document platform dependent behavior of iconify, withdraw, deiconify, raise, etc.
Type: RFE Version: 8.7
Submitter: marc_culler Created on: 2017-11-22 03:52:11
Subsystem: 65. Generic Window Operations Assigned To: nobody
Priority: 3 Low Severity: Important
Status: Open Last Modified: 2019-11-14 21:17:37
Resolution: None Closed By: nobody
    Closed on:
Description:
This seems like a fairly basic bug.

If I run this on Ubuntu 16.04, the window .t does not reappear on the screen:

$ wish8.7
% toplevel .t
.t
% wm iconify .t
% wm deiconify .t

On the other hand, if I run this, the window does reappear:

$ wish8.7
% toplevel .t
.t
% wm withdraw .t
% wm deiconify .t

I am using Tk 8.7 from check-in [dca999e4].
User Comments: tombert added on 2019-11-14 21:17:37:
Please also follow these reports here:

https://core.tcl-lang.org/tk/tktview/3131699cb421ec1de2b6fa08ff0835dd34eff3cb
https://gitlab.gnome.org/GNOME/mutter/issues/589

For me it more looks like a bug. The developer at "mutter" confirms that the behaviour changed but the documentation lacks behind.

bll added on 2017-11-30 15:34:59:
I actually hate that type of behaviour (Only in Windows, if I have an open window in active focus, and am actively using it, will the window manager _not_ raise a window over my active window and not steal the focus), so I am all for it not working.  Nevertheless, the behaviour should be consistent if possible.

On linux, the work-around is:
  wm attributes . -topmost 1
  update ; # probably
  wm attributes . -topmost 0

I am usually set to focus-follows-mouse everywhere, so I can't test focus changes of wish vs. other programs very easily.

marc_culler added on 2017-11-30 13:36:02:
The problem with the KDE behavior is that it means there is no way for an
application to raise one toplevel to the top of the stack by using the 'raise'
command. As a guess, that one use case accounts for 90% of the situations
where one would want to 'raise' a toplevel. So I would consider that to be
incorrect behavior, regardless of what the fine print in the manual may say.

A partial workaround on KDE is that 'focus .a' does raise the toplevel '.a'
to the top of the stacking order.  However, what it does not do, oddly
enough, is to give '.a' the focus.  On KDE the following commands:

toplevel .a
wm geometry .a +100+100
toplevel .b
wm geometry .b +120+120
focus .a

produce 3 windows, with '.a' above '.b' but the focus belongs to the root.
The same thing happens on Ubuntu Unity.

If the last line is changed to 'raise .a' then '.b' will remain in front of
'.a'.  The behavior of Ubuntu Unity is arguably worse, because it is
inconsistent.  Using 'focus .a' has the same effect on both systems, but
using 'raise .a' has different behaviors in Unity depending on how the
commands are run. If you type the commands above into the wish console using
'raise .a' as the last line, the toplevel '.a' goes to the top. But when the
same commands are run as a tcl script '.a' does not go to the top.

On Windows and macOS, 'raise .a' moves '.a' to the top of the stacking order.
Period.

bll added on 2017-11-30 11:17:37:
>  "If the aboveThis argument is omitted then the command raises window
>   so  that it is above all of its siblings in the stacking order"

I believe this refers to the case of:
   raise .toplevel.frame1.widget
will raise widget above all of its other siblings.

So it is not incorrect, just not applicable to top-level windows.

marc_culler added on 2017-11-30 05:56:24:
When I mentioned the ambguity of the manual page I was actually referring to
the manual page on my Ubuntu 16.04 system.  The manual page in the
core-8-6-branch has addressed this issue, and says that a toplevel may be
reordered with respect to all toplevels.  It also says that window managers
may not "strictly" honor requests to restack.  So maybe that lets KDE off the
hook.  Nevertheless, the behavior does vary a lot from one window manager to
the next.

marc_culler added on 2017-11-30 05:46:43:
Continuing the catalog of anomalies with the raise command, on KDE if you create
two toplevels '.a' and '.b' with '.b' higher in the stacking order than '.a', the command
%raise .a
has no effect whatsoever.  However, the command
%raise .a .b
will raise '.a' above '.b'.

This does not conform with the manual page, which says:

  "If  the aboveThis argument is omitted then the command raises window so
   that it is above all of its siblings in the stacking order"

Note also that this quote from the manual page is ambiguous.  It does not
say whether window should be raised above windows that are not siblings.
In the case above, should 'raise .a' raise '.a' above '.'? On Windows,
macOS and Ubuntu Unity that command raises '.a' above all on-screen windows,
regardless of whether they are siblings.

bll added on 2017-11-28 21:27:59:
Looks like XFCE is more like Windows.
De-iconifying a window always puts it on top.
This area seems to be highly wm dependent.

marc_culler added on 2017-11-28 20:53:14:
OK, I installed kubuntu17.10 on a VM.

With KDE, the wm remembers the position of a window in the stacking order when
it is iconified.  The raise command works to change the position of an iconified
window, and raising a window above an iconified window places it in the same
position that it would have if the target had not been iconified.  That is, the
window manager maintains a stacking order for all normal or iconified windows
as one group and raise has the expected effect on any window in the group.

If a raise operation involves a withdrawn window it is ignored.  Deiconifying
a withdrawn window puts it on top. There is no special case for the root window.
A window does not automatically get focus by being deiconified.

marc_culler added on 2017-11-28 18:07:07:
On Windows when a window is deiconified it goes to the top of the stacking order
no matter what.  Its position in the order when it was iconified does not affect
this, and neither do any raise operations applied to the window while it was
iconified.  So effectively the raise command is completely ignored when applied
to a window which is iconified.

When a normal window is raised above an iconified window it goes to the *bottom* 
of the stacking order, as if all inconified windows are below all normal
windows.  Similarly, raising a normal toplevel above a withdrawn window moves
it to the bottom of the stacking order.

However, the root window behaves differently from other toplevels with respect
to withdrawn windows.  Raising the root window above an iconified window moves
it to the bottom, but raising the root window above a withdrawn window has no
effect.

I think it would be a simple matter to implement the same behavior on the
Macintosh.  But the behavior seems a bit quirky, because it is exceptional
for the root window.  So this brings up the question of whether linux window
managers also behave this way.  (I can't easily test that at the moment
because all my linux systems have the bug.)

bll added on 2017-11-28 15:55:57:
Just for comparison purposes, here is KDE:

% wm iconify .
% wm state .
iconic
% raise .
% wm state .
iconic
% wm deiconify .
% wm state .
normal

bll added on 2017-11-28 15:43:34:
As cinnamon is based on gnome-shell and has the bug,
I don't think what it does can be trusted.
% wm iconify .
% wm state . 
normal           # wrong
% raise .
% wm state .
normal
% 

I would be inclined to think that Windows and Linux are processing the raise command correctly.  'raise' should not change the window state.

marc_culler added on 2017-11-28 15:17:35:
Apropos of the cinnamon behavior and the title of this ticket, the manual does
not say what should happen when an iconified window is raised.  Ticket [164c1b1091]
points out that the Aqua port deiconifies the window, while Windows and
some unspecified linux window managers do not deiconify it.

I am curious what happens on cinnamon.

Also, I think it would be nice if the manual were to specify a correct behavior
in this case.

bll added on 2017-11-28 13:42:44:
Also: https://bugs.launchpad.net/unity/+bug/998073

bll added on 2017-11-28 13:16:35:
Also tested with:
 8.6.5 - fail - linux mint 18.2 - cinnamon
Interesting that with cinnamon, you can do
 wm deiconify .
 raise .
as a work-around (the iconify is still slow),
but in Unity, the raise does not help.

Should text be added to the release notes?  Such as:

Due to a bug in gnome-shell and its variants (cinnamon, unity, etc.),
  ( https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1502370 )
'wm iconify/wm deiconify' will not work properly, and the state of the 
window is not properly updated when the window is minimized. The only work
around that can be suggested at this time is to use any window manager
that is not based on gnome-shell (e.g. kde, mate, fvwm, xfce, etc.).

kevin_walzer added on 2017-11-25 18:56:15:
Ah, so you mean add an entry to the Dock menu and the native Window menu (rather than its own icon per se). I can follow that line of thinking. Ensuring it does not appear in the Window menu just means some manual addition and deletion depending on the window state and that should not be too hard to implement. I am not certain how to access the Dock menu from Tk, but Cocoa does provide some hooks. At what point should we look at implementing this?

marc_culler added on 2017-11-25 15:11:26:
Incidentally, Tk for Windows behaves exactly as I was suggesting.  Windows
creates an icon in the task bar for each running application.  When you
hover the mouse over that icon a list of windows pops up.  Clicking on
an item in that list causes a normal window to be minimized or a minimized
window to be displayed.

With Windows Tk when you iconify a window it appears in the window list.
When you withdraw a window it does not appear in the window list and there
is no user action that will redisplay it on the screen.  When you deiconify
either an iconified window or a withdrawn window it reappears on the screen.

marc_culler added on 2017-11-25 14:43:46:
I should have added, that currently withdraw does not completely hide the
window.  It does not create an icon for the window in the dock but it does
add the window to the Window menu.  That tells the user that the window
exists and allows the window to be mapped to the screen.  The change in
behavior that I am advocating is simply to NOT put withdrawn windows into
the Window menu.

marc_culler added on 2017-11-25 14:29:47:
Kevin, I think you are misinterpreting what I said.  I was not referring to the
*application* icon.  I was referring to an icon for a minimized *window*.
Currently when you iconify a window in macOS a new icon is created in the dock
in addition to the application icon.  This is exactly the same thing that
happens when a window is minimized by clicking the yellow button in the title
bar.  In fact what Tk does to iconify a window is to call [NSWindow miniaturize].
And I think this is the correct behavior for iconify.

I think withdraw should be used for a different purpose.  There are many cases
where an application needs to be able to open many windows, say with each one
presenting a "document" of some sort, but has no need for a special "root"
window.  On other platforms this leads to things like spash windows whose only
purpose is to indicate that the application is active.  This is unnecessary
on the mac because the menu bar indicates that the application is active even
when it has no windows on the screen.  If you are writing such an app with Tk
you want to hide the root window from the user completely.  There is no point
in allowing the user to open up a blank 200x200 window.  You don't want the
root window to be minimized.  You want it to be invisible and inaccessible.
This is what withdraw should do for you.

kevin_walzer added on 2017-11-25 13:46:22:
I don't agree that a macOS app with a withdrawn window should have its Dock icon disappear. It's standard macOS behavior for a running application to display a Dock icon, even if no windows are visible, unless it is specifically designated as a background/faceless app via a flag in its Info.plist file. 

In fact, I'd suggest that the macOS behavior of these commands is correct in the context of the platform. wm_iconify minimizes the window, and wm_withdraw hides it. That's how other Mac apps behave. That may result in some inconsistency with other platforms that Tk runs on, but that's OK. There are other contexts where a native implementation may differ subtly from documented functionality; these differences should be noted, but not removed.

marc_culler added on 2017-11-25 13:00:21:
Thanks for the extensive testing!

If I ran the zoo, I think I would say that the correct behavior for withdraw
would be to remove the window from the screen, show no indicators that the
window exists and provide no means for the user to redisplay it with any input
actions.  Only calling deiconify should redisplay it.  On the other hand,
the correct behavior for iconify should be to remove it from the screen,
provide visual indication that the window exists and provide some way for the
user to redisplay it.  It should also be redisplayable with iconify.

The macOS behavior would be wrong, according to this.  A withdrawn window
should have no dock icon and should not be listed in the Apple Window menu.
An iconified window should have both a dock icon and a listing in the Window
menu, either of which can be used to redisplay it.

The Unity and gnome-3 behavior would also be wrong, since iconify does not
work to redisplay a window which has been iconified.

bll added on 2017-11-25 00:55:22:
This is relevant:

https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1502370

If multiple people report on it, the bug may gain some traction.

(and would someone fix the login problem with this *&#$& ticket system).

bll added on 2017-11-25 00:14:16:
This may be relevant:

https://stackoverflow.com/questions/30192347/how-to-restore-a-window-with-xlib

I wonder how to test to see if gnome-shell is active.  This bug is going
to be really annoying.   And the long timeout to execute a 'wm iconify' will
be a problem.

bll added on 2017-11-24 23:53:40:
My comment (a) is no good.  'wm iconify' on XFCE allows the icon/window to be
displayed in the window list.  'wm withdraw' does not display the icon/window in
the window list.  There are probably a dozen different window list variants across the different window managers, but I assume that they will all more or
less work the same way.

So this is the same action as on Mac OS X.

bll added on 2017-11-24 23:20:12:
The gnome-3 based window managers have the bug.

Work around: Use a window manager that is not based on gnome-3.

a) Is there any particular reason to keep the old 'wm iconify' code 
for unix systems?  The old style of putting icons on to the desktop
is long gone.  As Marc suggests, the unix systems can simply process
the request in the same manner as 'wm withdraw'.

As this bug is present in the default window manager for Ubuntu LTS systems
and the default window manager in Red Hat based systems, it may be
worthwhile getting this change into 8.6.8.

b) In the time being, the documentation can be updated to reflect
that 'wm withdraw' is the preferred method for unix systems, and note
the differences between 'wm iconify' and 'wm withdraw' on Mac OS X.

8.6.7  - ok   - MX 17.1 - xfce
8.6.1  - ok   - Ubuntu 15.02 - mate
8.6.5  - fail - Ubuntu 16.04.2 - unity
8.6.5  - fail - Ubuntu 16.04.3 - unity
8.6.5  - ok   - Ubuntu 16.04.3 - mate
8.6.5  - ok   - Ubuntu 16.04.3 - xfce
8.6.6  - fail - Ubuntu 16.10 - unity
8.6.1  - ok   - Linux Mint 17 - mate
8.6.5  - ok   - Linux Mint 18.2 - kde
8.6.2  - ok   - Debian 8.8 - mate
8.6.6  - ok   - Ubuntu 17.04 - kde
8.6.6  - ok   - Ubuntu 17.04 - mate
8.6.6  - fail - Ubuntu 17.04 - gnome 3
8.6.7  - ok   - Manjaro 17 - xfce
8.5.13 - fail - CentOS 7 - gnome 3
8.6.6  - fail - Fedora 25 - gnome 3

bll added on 2017-11-24 20:36:54:
Note that this is Linux version dependent and is very 
possibly a window manager bug.
Unfortunately, Ubuntu 16.04 is a LTS version (now at 16.04.3).

MX Linux (Debian Jessie) w/XFCE: no issues.

I'll see if I can make a chart.

marc_culler added on 2017-11-22 13:28:56:
The man page is clear enough:  "Arrange for window to be  displayed in normal
(non-iconified) form."  But that is not what happens on Ubuntu.

The claim in that thread is that this is an Ubuntu bug.  But the fact that
deiconify does work correctly for a withdrawn window means that it would be
possible for Tk to create the correct behavior on Ubuntu.  Evidently it
doesn't create the correct behavior because the Tk code handles the process
of deiconifying an iconified window differently from how it handles
deiconifying a withdrawn window.

Presumably this difference is based on some unspecified abstract model of how
a window manager should behave.  It is not so clear to me that Ubuntu's
failure to adhere to that model represents a bug in Ubuntu's window manager.
In fact, I suspect that the percentage of window managers which do fit that
model is pretty small these days.  For example, the manual says that withdraw
makes the window "forgotten about by the window manager".  But that is
not what happens on the aqua platform.  There the difference between iconify
and withdraw is that iconify puts an icon on the dock while withdraw doesn't.
But both of them leave the window in the Window menu, which can be used to
redisplay the window on the screen.  So the window is not "forgotten".

A concrete suggestion would be for the manual to say that the behaviors of
iconify, withdraw, deiconify, raise (see ticket 164c1b1091) and lower are
heavily dependent on the window manager, and to provide or refer to a table
showing what the behaviors are (or should be) for the most common window
managers, e.g. gnome, kde, ubuntu, Windows, macOS.  Currently the manual
discusses separately what happens with Windows, suggesting that there are
only two behaviors: Windows and everything else.  This is misleading.

The bottom line is that people who are maintaining applications that are
intended to run on many platforms need to know what behavior to expect on
each platform that they support. They shouldn't have to run experiments
on each one.  And when they find unexpected behaviors they should be able
to determine whether they are seeing a bug.

Of course one expects such an application to have some platform-dependent
code that can compensate for different behaviors.  This is problematic,
though, when the code needs to know not only which platform it is running
on but also which of many possible window managers it is using on that
platform.  In my case, where the application is written in Python and uses
Tk via the tkinter module, I do not know how get that information.  Perhaps
it is possible though.

fvogel added on 2017-11-22 04:56:21:

Isn't this invalid?

See this recent thread in comp.lang.tcl

Perhaps the man page is not clear enough since this comes back from time to time. Suggestions welcome.