resizing with gravity



I spent the weekend communing with the ICCCM and the EWMH and will be
sending a bunch of messages...

My first issue is with window gravity. The EWMH says:

> Window manager implementors should refer to the ICCCM for definitive
> specifications of how to handle MapRequest and ConfigureRequest
> events. However, since these aspects of the ICCCM are easily misread,
> this document offers the following clarifications:

And then it proceeds to explain window gravity in a manner that, I'm
fairly certain, is exactly wrong:

> If an Application requests just a new size, its reference point does
> not move. So for example if client window has win_gravity
> SouthEastGravity and is resized, the bottom right corner of its frame
> will not move but instead the top left corner will be adjusted by the
> difference in size.

There is nothing in the ICCCM that supports this idea. This seems to be
confusing the win_gravity WM_NORMAL_HINTS field with the win_gravity
XWindowAttributes field, which has the same name and uses the same
values, but is otherwise unrelated (and doesn't normally apply to
top-level windows).

Here's the entirety of what the ICCCM says about
WM_NORMAL_HINTS.win_gravity:

> 4.1.2.3. WM_NORMAL_HINTS Property
>
> The win_gravity may be any of the values specified for WINGRAVITY in
> the core protocol except for Unmap : NorthWest (1), North (2),
> NorthEast (3), West (4), Center (5), East (6), SouthWest (7), South
> (8), and SouthEast (9). It specifies how and whether the client window
> wants to be shifted to make room for the window manager frame.
>
> If the win_gravity is Static , the window manager frame is
> positioned so that the inside border of the client window inside the
> frame is in the same position on the screen as it was when the
> client requested the transition from Withdrawn state. Other values
> of win_gravity specify a window reference point. For NorthWest ,
> NorthEast , SouthWest , and SouthEast the reference point is the
> specified outer corner of the window (on the outside border edge).
> For North , South , East , and West the reference point is the
> center of the specified outer edge of the window border. For Center
> the reference point is the center of the window. The reference point
> of the window manager frame is placed at the location on the screen
> where the reference point of the client window was when the client
> requested the transition from Withdrawn state.
>
> 4.1.5. Configuring the Window
>
> The border width to be used and win_gravity position hint to be used
> are those most recently requested by the client.

"It specifies how and whether the client window wants to be shifted *to
make room for the window manager frame*." That is the ONLY meaning that
the ICCCM gives to that field, and there's nothing in 4.1.5 to suggest
anything beyond that.

Furthermore, interpreting gravity the way the EWMH does violates one of
the core principles of the ICCCM:

> It is a principle of these conventions that a general client should
> neither know nor care which window manager is running or, indeed, if
> one is running at all.

A principle which the EWMH even quotes at one point:

> To fulfill the ICCCM principle that clients should behave the same
> regardless whether a window manager is running or not...

The X server does not look at WM_NORMAL_HINTS. Thus, in the absence of a
window manager, it is always the top-left corner of the window that
remains pinned when the window is resized. Thus, an application that
depends on the EWMH-specified behavior will behave incorrectly if no WM
is running. (qv http://bugzilla.gnome.org/show_bug.cgi?id=338729)

(So what's the point of the hint then? If an app wants to place itself
in the lower-right corner of the screen, it should set its location to
(screen_width - window_width, screen_height - window_height), with
SouthEast WM_NORMAL_HINTS.win_gravity, and then if there is no window
manager running, it will be placed flush against the corner of the
screen, but if there *is* a window manager running, the wm will move the
window up and to the left a few pixels so that the *window manager
frame* is placed up against the edge of the screen, rather than being
placed offscreen. Then if the window wants to resize itself while
staying in the lower-left corner, it should simultaneously resize itself
and move itself to (screen_width - new_window_width, screen_height -
new_window_height), which again will result in either the window itself
or the wm frame being flush against the edge of the screen, depending on
whether or not a wm is running. The app behaves "the same" whether a
windowmanager is running or not.)


So, I recommend that that section of the EWMH be gutted and rewritten
(I'll provide text if there is consensus that this is correct, though I
haven't yet re-figured-out the parts about compensating for
border_width), with a note pointing out that (a) a previous version of
the spec recommended the wrong behavior, and (b) pre-EWMH window
managers have differed in how they interpreted this anyway, and so
therefore Clients SHOULD always include x and y coordinates in
ConfigureRequests and _NET_MOVERESIZE_WINDOW requests for windows with
non-NorthWest, non-Static gravity, to ensure that they get the behavior
they want.

-- Dan



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]