Re: struts, workareas and xinerama



2009/11/20 Tomáš Janoušek <tomi nomi cz>:
> Hello,
>
> On Thu, Jan 24, 2008 at 07:19:10PM +0100, Lubos Lunak wrote:
>> On Wednesday 13 of June 2007, Dana Jansens wrote:
>> > Secondly, I am in need of some clarification in terms of struts with
>> > Xinerama. In the above example, say an application set a strut on the
>> > "right side" with a length of the 1st monitor.  Where exactly does
>> > this strut reside? It could reside entirely on the first monitor, it
>> > could reside on the second monitor (and the nowhereland above it) or
>> > it could be split between the two monitors.
>> >
>> > I expect there is no answer to this question, which is frustrating
>> > because this is a real-life setup that one of my users has talked
>> > about recently.  Perhaps _NET_WM_STRUT_PARTIAL is just not enough, and
>> > needs to be able to specify the monitor as well as start/length.
>>
>>  Correct. The strut hints talk about desktop (root window) edges, so they
>> don't support reserved areas "inside". That basically matches _NET_WORKAREA,
>> so if you want to extend one, you probably want to do the same with the other
>> one.
>
> I encountered this issue as well and I got an idea for a simple workaround.
> Imagine a screen layout like this:
>
>    11111111
>    11111111
>    11111111
>     222222    <--- strut here
>     222222
>     222222
>
> We want to place a panel at the top of screen 2. A naive panel application may
> set a partial strut where top = top coordinate of screen 2 + height of panel.
> This is wrong, as it indicates that the entire screen 1* is covered, *but* the
> interpretation may as well be different. If we agree that struts covering an
> entire xinerama screen are nonsense, we may interpret such struts as not
> covering those screens at all, just those that they don't cover entirely. This
> way _NET_WM_STRUT_PARTIAL can be used for struts covering any edge of any
> Xinerama screen.
>
> * I know, not really entire screen. Just a horizontal strut whose height is
>  greater than the height of screen 1. Please read "entire" as "entire in
>  their primary dimension".
>
> This naive way of setting _NET_WM_STRUT_PARTIAL is used in xmobar and I have
> implemented this semantics for xmonad:
> http://www.haskell.org/pipermail/xmonad/2009-November/009148.html
>
> I can't think of any use for struts that span multiple screens in their primary
> dimension (height for horiz. struts, width for vert. struts), personally.
> If wm-spec is extended in the way Dana and Lubos said (which didn't happen yet
> even though it's been almost 2 years already), I'll be happy to implement it,
> but this "hack" seemed easier and compatible with what was in the wild.
>
> What's your opinion?

I apologize I dropped the ball on this one and forgot about it until
quite recently when another issue came up.

I have attached a suggested patch to the wm-spec to improve its
relation to multi-monitor environments.

First, it adds a multi-monitor-friendly _NET_WORKAREAS hint, replacing
the _NET_WORKAREA hint.  I thought that _NET_WORKAREAS sounded a bit
better than _NET_WORKAREA_AREAS, though it may be too close to the
original hint.  The hint is slightly different from the one I
suggested previously.  It looks like this:

_NET_WORKAREAS,	monitor, x, y, width, height, CARDINAL[][5]/32

I included a monitor index to each geometry so that a client can tell
how many monitors and desktops are being represented in this hint
independent of the value in _NET_NUM_DESKTOPS.  If decoding the values
in this required knowing the value of _NET_NUM_DESKTOPS, it would lead
to some ugly race conditions.

The proposed property lists the geometry of work areas on each monitor
for the first desktop, followed by the work areas on each monitor for
the second desktop, and so on.  The geometries are given for monitors
in the same order as the monitors appear in the list returned by the
Xinerama extension, and the "monitor" field is an index into this
list.

Secondly, as Lubus suggested, I have extended the STRUT property to
allow for placing struts on boundaries between monitors.  This
addresses the use case presented by Tomáš. To keep the property
similar to what has been done in the past, my proposed property looks
like this:

_NET_WM_STRUT_AREAS, monitor, left, right, top, bottom, left_start_y,
left_end_y,
right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
bottom_end_x, CARDINAL[13]/32

As you can see it is exactly the _NET_WM_STRUT_PARTIAL hint, with a
monitor field added, so that the window can request the monitor on
which the strut should be reserved.

In both cases of these hints, monitor may be set to 0xFFFFFFFF, in
which case the geometry is relative to the root window and ignores
everything about multiple monitors, essentially using the same
behavior as the old hints.


I would however like to understand why the _NET_WM_STRUT (and then
_NET_WM_STRUT_PARTIAL) hint allows a window to reserve space along
more than one edge of the screen.  This makes it very difficult for a
window manager to do anything intelligent with strut windows, as it
can not always tell what edge they are on if they request space on
multiple edges.  What use case was considered when allowing this
behaviour?  It is included in the notes that "A corner panel that does
not extend for the full length of a screen border SHOULD only set one
strut."  I would perfer to make the _NET_WM_STRUT_AREAS hint only
allow an application to reserve one rectangular area along one edge of
one monitor.  Applications which wanted to use multiple edges could
still do so through multiple windows.

Restricting a window to reserving a strut along only one edge would
not affect most (any?) uses of the STRUT property for applications,
but would allow a Window Manager to treat strut windows more
intelligently.  The use case I am considering this for is when more
than one window reserve the same edge of a screen [1].  Currently
applications are trying to place themselves relative to the WORKAREA,
which causes race conditions between clients and does not allow them
to properly move dynamically as strut windows are added/removed along
the edge.  The window manager should be able to place windows along a
strut edge when there are more than one so that they do not overlap.
This would be much simpler and more predictable if a window is only
attached to a single edge (has a single reserved edge reserved in its
strut).

I have added a comments in the diff that reflect the problems
introduced in this scenario.  First that the STRUT should be relative
to the screen edge, not to the WORKAREA, and second that the window
manager may place windows with struts away from the edge of the
monitor.  However, implementations will be somewhat limited by the
STRUT hint in its current form.  These are important things that will
affect how well applications will be able to make use of struts, and
cooperate with each other, so I hope that these issues will be looked
at seriously.

Cheers,
Dana


[1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=551807
commit 39d82f6ff7ed2a552fbecd8c032e0190f918135f
Author: Dana Jansens <danakj orodu net>
Date:   Fri Nov 20 23:25:20 2009 -0500

    Add _NET_WORKAREAS and _NET_WM_STRUT_AREAS.

diff --git a/wm-spec.xml b/wm-spec.xml
index f45e284..f3ed0fc 100644
--- a/wm-spec.xml
+++ b/wm-spec.xml
@@ -340,7 +340,7 @@ _NET_NUMBER_OF_DESKTOPS
   other data.l[] elements = 0
 ]]></programlisting>
 	<para>
-The Window Manager is free to honor or reject this request. If the request is honored _NET_NUMBER_OF_DESKTOPS MUST be set to the new number of desktops, _NET_VIRTUAL_ROOTS MUST be set to store the new number of desktop virtual root window IDs and _NET_DESKTOP_VIEWPORT and _NET_WORKAREA must also be changed accordingly. The _NET_DESKTOP_NAMES property MAY remain unchanged.
+The Window Manager is free to honor or reject this request. If the request is honored _NET_NUMBER_OF_DESKTOPS MUST be set to the new number of desktops, _NET_VIRTUAL_ROOTS MUST be set to store the new number of desktop virtual root window IDs and _NET_DESKTOP_VIEWPORT and _NET_WORKAREAS must also be changed accordingly. The _NET_DESKTOP_NAMES property MAY remain unchanged.
 	</para>
 	<para> 
 If the number of desktops is shrinking and _NET_CURRENT_DESKTOP is out of the new range of available desktops, then this MUST be set to the last available desktop from the new set.  Clients that are still present on desktops that are out of the new range MUST be moved to the very last desktop from the new set. For these _NET_WM_DESKTOP MUST be updated.
@@ -479,24 +479,71 @@ Depending on the information provided with the message, the Window Manager may
 decide to refuse the request (either completely ignore it, or e.g. use
 _NET_WM_STATE_DEMANDS_ATTENTION).
         </para>
+	</sect2><sect2><title>_NET_WORKAREAS</title>
+	<programlisting><![CDATA[
+_NET_WORKAREAS, monitor, x, y, width, height, CARDINAL[][5]/32
+]]></programlisting>
+	<para>
+This property MUST be set by the Window Manager upon calculating the work area
+for each desktop. Contains a geometry of the working area on each physical
+monitor (provided by the Xinerama extension), for each virtual desktop.
+All connected monitors SHOULD have a geometry included,
+and the same monitors MUST be represented for all desktops.
+The monitor is an index into the list of monitors returned by the Xinerama
+extension, starting from 0, or can be a value of 0xFFFFFFFF to indicate the
+Window Manager does not support multiple monitors, and the work area is
+spread across the entire root window.  The geometry for each monitor MUST
+appear in this property, for each desktop, in the same order reported by the
+Xinerama extension.
+These geometries are specified relative to the viewport on each
+desktop, not relative to the monitor, and specify an area that is completely
+contained within the viewport.
+Work areas SHOULD be used by desktop applications to place desktop icons
+appropriately.
+	</para>
+	<para>
+This property holds a list of work areas for the first desktop, across all
+monitors, followed by a list of work areas for the second desktop, and so on.
+For example, consider the scenario where there is one monitor of size
+1280x1024 and a second monitor of size 1024x768.  The Window Manager has
+2 desktops, and there are is a reserved area of 20 pixels at the top of the
+second monitor on only the second desktop.  Then this property would look like:
+"0, 0, 0, 1280, 1024, 1, 0,  0, 1024, 768,
+ 0, 0, 0, 1280, 1024, 1, 0, 20, 1024, 748".
+Alternatively, consider if a Window Manager does not support multiple monitors
+through Xinerama, but sees a root window of size 2304x1024 with 2 desktops
+and 20 pixels reserved at the top of the screen on the second desktop.
+Then this property would look like:
+"0xFFFFFFFF, 0, 0, 2304, 1024, 0xFFFFFFFF, 0, 20, 2304, 1004".
+	</para>
+	<para>
+The Window Manager SHOULD calculate this space by taking the current
+page minus space occupied by dock and panel windows, as indicated by
+the <link linkend="NETWMSTRUTAREAS">_NET_WM_STRUT_AREAS</link>
+property set on client windows (or
+<link linkend="NETWMSTRUT">_NET_WM_STRUT</link> and
+<link linkend="NETWMSTRUTPARTIAL">_NET_WM_STRUT_PARTIAL</link> properties
+for legacy clients).
+	</para>
 	</sect2><sect2><title>_NET_WORKAREA</title>
 	<programlisting><![CDATA[
 _NET_WORKAREA, x, y, width, height CARDINAL[][4]/32
-]]>
-	</programlisting>
+]]></programlisting>
 	<para>
-This property MUST be set by the Window Manager upon calculating the work area for  
+This property has been DEPRECATED in favor of _NET_WORKAREAS.  When
+_NET_WORKAREAS has been set, clients MUST ignore the value of this
+property, and use _NET_WORKAREAS instead. Window Managers MAY
+continue to update this property for legacy applications.
+	</para>
+	<para>
+This property MAY be set by the Window Manager upon calculating the work area for
 each desktop.  Contains a geometry for each desktop.  These geometries are 
 specified relative to the viewport on each desktop and specify an area that is
 completely contained within the viewport.
- Work area SHOULD be used by desktop applications to place desktop icons appropriately.
 	</para>
 	<para>
-The Window Manager SHOULD calculate this space by taking the current
-page minus space occupied by dock and panel windows, as indicated by
-the <link linkend="NETWMSTRUT">_NET_WM_STRUT</link> or <link
-linkend="NETWMSTRUTPARTIAL">_NET_WM_STRUT_PARTIAL</link> properties set on
-client windows.
+The Window Manager SHOULD calculate this space as a subset of the areas
+described in _NET_WORKAREAS.
 	</para>
 	</sect2>
 	<sect2>
@@ -1332,48 +1379,59 @@ _NET_WM_ACTION_BELOW indicates that the window may placed in the "below" layer o
 	</para>
 </sect2>
 
-<sect2><title>_NET_WM_STRUT</title>
-	<programlisting id="NETWMSTRUT"><![CDATA[
-_NET_WM_STRUT, left, right, top, bottom, CARDINAL[4]/32
-]]></programlisting>
-	<para>
-This property is equivalent to a _NET_WM_STRUT_PARTIAL property where all start
-values are 0 and all end values are the height or width of the logical screen.
-_NET_WM_STRUT_PARTIAL was introduced later than _NET_WM_STRUT, however, so
-clients MAY set this property in addition to _NET_WM_STRUT_PARTIAL to ensure
-backward compatibility with Window Managers supporting older versions of the
-Specification.
-	</para>
-</sect2>
-<sect2><title>_NET_WM_STRUT_PARTIAL</title>
-	<programlisting id="NETWMSTRUTPARTIAL"><![CDATA[
-_NET_WM_STRUT_PARTIAL, left, right, top, bottom, left_start_y, left_end_y,
+<sect2><title>_NET_WM_STRUT_AREAS</title>
+	<programlisting id="NETWMSTRUTAREAS"><![CDATA[
+_NET_WM_STRUT_AREAS, monitor, left, right, top, bottom, left_start_y, left_end_y,
 right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
-bottom_end_x,CARDINAL[12]/32
+bottom_end_x, CARDINAL[13]/32
 ]]></programlisting>
 	<para>
-This property MUST be set by the Client if the window is to reserve space at the
-edge of the screen.  The property contains 4 cardinals specifying the width of
+This property MUST be set by the Client if the window is to reserve space
+at the edge of a screen.  The property contains 1 cardinal specifying the
+monitor on which to reserve space, with 4 cardinals specifying the width of
 the reserved area at each border of the screen, and an additional 8 cardinals
-specifying the beginning and end corresponding to each of the four struts.  The
-order of the values is left, right, top, bottom, left_start_y, left_end_y,
+specifying the beginning and end corresponding to each of the four struts.
+The order of the values is left, right, top, bottom, left_start_y, left_end_y,
 right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
-bottom_end_x. All coordinates are root window coordinates. The client MAY change
+bottom_end_x. The monitor is specified as an index from 0 into the list
+of monitors given by the Xinerama extension, or may be 0xFFFFFFFF to
+specify that the strut is to be placed along the edge of the root window
+(the combination of all monitors).
+All coordinates are relative to edge of the physical monitor on which space
+is being requested (not relative to the values in _NET_WORKAREAS).
+The client MAY change
 this property at any time, therefore the Window Manager MUST watch for
 property notify events if the Window Manager uses this property to assign
 special semantics to the window.
 	</para>
 	<para>
-If both this property and the _NET_WM_STRUT property are set, the Window Manager
-MUST ignore the _NET_WM_STRUT property values and use instead the values for
-_NET_WM_STRUT_PARTIAL.  This will ensure that Clients can safely set both
+A client MUST NOT attempt to set its strut according to other windows
+with struts on the monitor, or according to the _NET_WORKAREAS property,
+as these create race conditions between clients. Instead the size of the
+reserved area MUST always be relative to the screen edge, as if the
+client is the only window with a strut along that edge. If multiple
+windows have overlapping struts along a screen edge, the Window Manager
+MAY adjust the positions of the windows on screen to prevent the
+windows from visibly overlapping by moving the windows away from the
+reserved edge of the screen. Thus a client with a strut window MUST allow
+for the Window Manager to place the window in a different position than
+requested, though it can expect to be placed logically along the edge
+requested.
+	</para>
+	<para>
+If both this property and the _NET_WM_STRUT or _NET_WM_STRUT_PARTIAL property
+are set, the Window Manager
+MUST ignore the _NET_WM_STRUT and _NET_WM_STRUT_PARTIAL property values and use
+instead the values for
+_NET_WM_STRUT_AREAS.  This will ensure that Clients can safely set both
 properties without giving up the improved semantics of the new property.
 	</para>
 	<para>
 The purpose of struts is to reserve space at the borders of the
 desktop.  This is very useful for a docking area, a taskbar or a panel,
-for instance. The Window Manager should take this reserved area into
-account when constraining window positions - maximized windows, for
+for instance. The Window Manager SHOULD take this reserved area into
+account when determining the desktop geometry in _NET_WORKAREAS,
+and when constraining window positions - maximized windows, for
 example, should not cover that area.
 	</para>
 	<para> 
@@ -1389,13 +1447,13 @@ screen, 50 pixels tall, and occupying the space from 200-600 pixels
 from the left of the screen edge would set a bottom strut of 50, and
 set bottom_start_x to 200 and bottom_end_x to 600.  Another example is
 a panel on a screen using the Xinerama extension.  Assume that the set
-up uses two monitors, one running at 1280x1024 and the other to the
-right running at 1024x768, with the top edge of the two physical
-displays aligned.  If the panel wants to fill the entire bottom edge
+up uses two monitors, the first one running at 1280x1024 and a second
+one to the right running at 1024x768.
+If the panel wants to fill the entire bottom edge
 of the smaller display with a panel 50 pixels tall, it should set a
-bottom strut of 306, with bottom_start_x of 1280, and bottom_end_x of
-2303.  Note that the strut is relative to the screen edge, and not the
-edge of the xinerama monitor.
+bottom strut of 50 on monitor 1, with bottom_start_x of 0, and bottom_end_x of
+768.  Note that the strut is relative to the edge of the xinerama monitor on
+which it is being placed.
 	</para>
 	<para>
 Rationale: A simple "do not cover" hint is not enough for dealing with e.g.
@@ -1407,6 +1465,38 @@ A "corner" panel that does not extend for the full length of a screen border
 SHOULD only set one strut.
 	</para>
 </sect2>
+<sect2><title>_NET_WM_STRUT</title>
+	<programlisting id="NETWMSTRUT"><![CDATA[
+_NET_WM_STRUT, left, right, top, bottom, CARDINAL[4]/32
+]]></programlisting>
+	<para>
+This property is equivalent to a _NET_WM_STRUT_AREAS property where all start
+values are 0, all end values are the height or width of the logical screen,
+and the monitor is the first monitor.
+_NET_WM_STRUT_AREAS was introduced later than _NET_WM_STRUT, however, so
+clients MAY set this property in addition to _NET_WM_STRUT_AREAS when a Window
+Manager advertises support for it, but not for _NET_WM_STRUT_AREAS, to ensure
+backward compatibility with Window Managers supporting older versions of the
+Specification.
+	</para>
+</sect2>
+<sect2><title>_NET_WM_STRUT_PARTIAL</title>
+	<programlisting id="NETWMSTRUTPARTIAL"><![CDATA[
+_NET_WM_STRUT_PARTIAL, left, right, top, bottom, left_start_y, left_end_y,
+right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
+bottom_end_x,CARDINAL[12]/32
+]]></programlisting>
+	<para>
+This property is equivalent to a _NET_WM_STRUT_AREAS property with the same
+start and end values, for the first monitor reported by the Xinerama
+extension.
+_NET_WM_STRUT_AREAS was introduced later than _NET_WM_STRUT_PARTIAL, however, so
+clients MAY set this property in addition to _NET_WM_STRUT_AREAS when a Window
+Manager advertises support for it, but not for _NET_WM_STRUT_AREAS, to ensure
+backward compatibility with Window Managers supporting older versions of the
+Specification.
+	</para>
+</sect2>
 <sect2><title>_NET_WM_ICON_GEOMETRY</title>
 <programlisting><![CDATA[
 _NET_WM_ICON_GEOMETRY, x, y, width, height, CARDINAL[4]/32
@@ -2245,6 +2335,14 @@ OR OTHER DEALINGS IN THE SOFTWARE.
  		<title>Changes since 1.3</title>
  		<itemizedlist>
  			<listitem><para>
+Added _NET_WM_STRUT_AREAS, deprecating _NET_WM_STRUT_PARTIAL and _NET_WM_STRUT,
+to improve support for applications in multi-monitor environments.
+			</para></listitem>
+ 			<listitem><para>
+Added _NET_WM_WORKAREAS, deprecating _NET_WM_WORKAREA, to improve support for
+applications in multi-monitor environments.
+			</para></listitem>
+ 			<listitem><para>
 Added _NET_WM_MOVERESIZE_CANCEL.
 			</para></listitem>
 			<listitem><para>


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