Documenting 'wm geometry'

It transpires that the behaviour of [wm geometry ...] is quite different between the standard Tk platforms. This page is to document those differences (since the wm man page doesn't do so).

The main differences are between whether this command manipulates/queries the entire window including borders/titlebar or just the contents, and in what aspects can be set/queried during a window's creation or while it is withdrawn.

Difference 1: wm geometry . +0+0

Windows
'wm geometry . +0+0' will move the main toplevel so that it nestles into the top-left corner of the screen, with the left border and titlebar completely visible.
MacOS X
'wm geometry . +0+0' will move the main toplevel so that it nestles into the top-left corner of the screen, with the left border completely visible. The titlebar is also within the screen, but it (and possibly a few pixel rows of contents) is completely obscured by the menu bar.
X11
'wm geometry . +0+0' will move the main toplevel so that its contents are nestled into the top-left corner of the screen, but with the left border and titlebar completely offscreen and invisible.

In summary positioning with wm geometry controls the window contents on X11, but the window structure on Windows/MacOS X.

This is in contrast to winfo rooty/rootx $w which deals with window contents on all platforms.

JE This depends on the window manager. Under metacity (Gnome's WM), twm, and others, wm geometry . +$x+$y places the upper-left corner of the window decoration at $x,$y; under MWM and 4DWM, it places the upper-left corner of the window contents there. I'm pretty sure this is because tkUnixWm.c isn't doing the right thing according to the ICCCM -- it looks like it's trying to implement the first behaviour (place window decorations), but it does so by attempting to second-guess what the WM is going to do. Under many WMs, it guesses wrong.

Difference 2: window decoration geometry

Because of Difference 1, the following proc

    proc decorationGeometry {{w .}} {
        set geom [wm geometry $w]
        regexp -- {([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)} $geom -> \
          width height decorationLeft decorationTop
        set contentsTop [winfo rooty $w]
        set contentsLeft [winfo rootx $w]
        # Measure left edge, and assume all edges except top are the
        # same thickness
        set decorationThickness [expr {$contentsLeft - $decorationLeft}]

        # Find titlebar + menubar (if it exists) thickness
        set titleMenubarThickness [expr {$contentsTop - $decorationTop}]

        return [list $titleMenubarThickness $decorationThickness]
    }

Is only useful on MacOS X/Windows (where it returns the thickness of the titlebar/menubar and the thickness of the left window border). On X11, it simply returns 0 0.

Difference 3: geometry of withdraw windows

On immediate creation:

    toplevel .tt ; wm withdraw .tt ; wm geometry .tt

will return 1x1+0+0 on all platforms, but:

    toplevel .tt ; wm withdraw .tt ; update; wm geometry .tt

will return 1x1+0+0 on X11, 200x200+198+261 (or something similar) on Windows, and 1x1+45+85 (or something similar) on OS X. Similarly, winfo height .tt will return (of course) 1 on x11 and 200 on Windows.

A constant here is that winfo reqheight .tt will return 200 (or equivalent) on all platforms. So there is at least a workaround for this difference in behaviour.

LES on May 27, 2004: I've been doing experiments and also get 200 in winfo reqheight consistently. The text above says that winfo reqheight will return 200. What is the use of a variable whose value is always the same?

MG - I believe that the point is that (at least, on Windows) a window's default/original height is 200, when it's mapped. winfo reqheight can be used at other times to when a window is mapped, though. When it was said above that it ''will' return 200, it refered only to the use specifically mentioned above (and the only on that particular OS, as others will no doubt use different default/minimum/etc window sizes).

Difference 4: ...


More to be filled in.

...


laterne - 2015-06-19 08:09:45

The regular expression in Difference 2 should be

{^(0-9+)x(0-9+)(+-)(\-?0-9+)(+-)(\-?0-9+)$}

to handle negative positions and orientations