Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

wlr-output-layout: relative auto layouts #550

Closed
acrisci opened this issue Jan 4, 2018 · 7 comments
Closed

wlr-output-layout: relative auto layouts #550

acrisci opened this issue Jan 4, 2018 · 7 comments

Comments

@acrisci
Copy link
Contributor

acrisci commented Jan 4, 2018

Support adding an output to the layout in a position relative to another output (sort of like xrandr --output op1 --left-of op2).

The layout should automatically adjust to make sure the output comes as close as possible to being in the relative location adjacent to the absolute output without overlapping another output.

enum wlr_output_layout_relative_position {
    WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_LEFT_OF,
    WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_RIGHT_OF,
    WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_ABOVE,
    WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_BELOW,
};

/**
 * Add an auto configured output to the layout relative to another output.
 * This will place the relative output as close as possible to the border of
 * the absolute output without overlapping another output. The output layout
 * will adjust dynamically to keep the relative output in this position when
 * the absolute output changes coordinates. If either output is not in the
 * output layout, it will be added. If the position of the relative output is
 * set to absolute coordinates, it will become manually configured.
*/
wlr_output_layout_add_auto_relative(struct wlr_output *output_relative,
        enum wlr_output_layout_relative_position position,
        struct wlr_output *output_absolute);
@VincentVanlaer
Copy link
Contributor

I have implemented most of this but with different behavior than described in this issue. I don't like the rule for overlapping outputs. While it might seem sensible to check for overlapping outputs, I feel that it adds unnecessary complexity. On top of that, the configuration will be order dependent and might change drastically when outputs are added or removed. Personally, I think not using collision detection makes it more clear to the user what is happening.

Autoconfigured outputs have the similar problems. I prefer it if their position is still chosen by the output layout code, but added as if they were manually added (the term fixed would be better to describe the state of the output). The only use case I see for the current implementation is when outputs are removed, the other outputs can move to the left and take its spot. But I think that can be supported just using relative positions. (This somewhat depends on the final implementation, since removing outputs is currently not supported in what I have written thusfar) On a side note, it might also be interesting to support placeholder outputs in the case a user unplugs and replugs an output, to prevent windows from migrating to one output while you want them to keep their position.

@acrisci
Copy link
Contributor Author

acrisci commented May 20, 2018

I don't like the rule for overlapping outputs.

My thought was that overlapping outputs are not very well supported by the library right now and are currently implementation specific, so not the primary use case for the output layout. To see an example of all the crazy things you can think of to do with overlapping outputs, see this. If people actually have a use case for overlapping outputs, then I'll change my mind. I personally think mirroring is a special case that could be handled better with a WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_MIRRORED flag and leave the rest for the normal use case of nonoverlapping outputs. However, if library users think overlapping outputs are actually usable and want that behavior, then that would be ok.

The use case I sort of had in mind for this was if you had one monitor that is always there, and the two to the right can come and go, you could say they are right of the main monitor, and you'll always get a usable output layout no matter if either are absent.

The nonoverlapping behavior also closely resembles the current auto layout function that we have.

On top of that, the configuration will be order dependent and might change drastically when outputs are added or removed.

Changing output layout location when outputs are added and removed is the whole point of "auto" layouts. That is, they "automatically" adjust themselves in certain situations like this.

Autoconfigured outputs have the similar problems. I prefer it if their position is still chosen by the output layout code, but added as if they were manually added

This is really easy to get. Just add the output as auto, and then manually set the position to whatever position the auto layout gives the output.

@VincentVanlaer
Copy link
Contributor

I don't like the rule for overlapping outputs.

My thought was that overlapping outputs are not very well supported by the library right now and are currently implementation specific, so not the primary use case for the output layout. To see an example of all the crazy things you can think of to do with overlapping outputs, see this. If people actually have a use case for overlapping outputs, then I'll change my mind. I personally think mirroring is a special case that could be handled better with a WLR_OUTPUT_LAYOUT_RELATIVE_POSITION_MIRRORED flag and leave the rest for the normal use case of non-overlapping outputs. However, if library users think overlapping outputs are actually usable and want that behavior, then that would be ok.

I have implemented a mirror option, that's something I'm definitely in favor of. Especially since it makes #878 easier to use. I also agree that the use case of overlapping, non-mirroring outputs is small. But I didn't mean to support this case, only to make the behavior less complex . I believe that an explicit configuration that is independent of the ordering in which outputs are configured is much clearer to the user. Even if that means that we get a not explicitly supported edge case (note that the user can easily trigger this by creating overlapping manual outputs, this is just another way of doing that). But ymmv.

The use case I sort of had in mind for this was if you had one monitor that is always there, and the two to the right can come and go, you could say they are right of the main monitor, and you'll always get a usable output layout no matter if either are absent.

That is indeed a valid use case, but I'm not sure if this is the way we would want to support that. For example, this causes the order of the outputs to change depending on the order you replug them. I would absolutely hate that. As a possible solution, I would rather have placeholder outputs which one can reference, but do not have a wlr_output associated with them until an output appears that matches certain criteria. (which will also make it easier to convert the config file to a layout, since not all of the outputs need to be present) These criteria can be set by the user. It would be necessary then to allow these fake outputs to make room for other outputs. Your example would have a configuration that looks something like

output O-1 fixed 0 0
output O-2 right of O-1 on removed replace by right
output O-3 right of O-2

Changing output layout location when outputs are added and removed is the whole point of "auto" layouts. That is, they "automatically" adjust themselves in certain situations like this.

That's fine by me. The only thing that I don't like about them is that they are order dependent, but if it is part of the contract, it doesn't bother me.

In my opinion, order independent configuration (I want to be able to remove and recreate any output on the backends without my layout changing, the only exception to this being the auto layout) and simpler code win from supporting every possible edge case, which can be solved by user configuration.

@acrisci
Copy link
Contributor Author

acrisci commented May 20, 2018

For example, this causes the order of the outputs to change depending on the order you replug them. I would absolutely hate that.

Yeah, that's not good behavior. But I don't think this is something we can handle well at the library level.

I think you're making a good case against auto layouts. It's prescriptive for how compositors should manage their layout and maybe the whole thing is better off living in the compositor application code. The add_auto() function is good for examples and prototypes where you don't want to think too hard about the layout though.

would rather have placeholder outputs which one can reference, but do not have a wlr_output associated with them until an output appears that matches certain criteria

Not a big fan of this idea because it creates a dead zone for the cursor. I think it would be better to warp between outputs in your application code when you hit an edge like xedgewarp (or manually manage your dead zones). I don't think edge warping behavior should be prescribed by wlroots either, but that's another issue.

However, I still think adding outputs to the output layout in a relative way is still a good feature for the output layout.

@VincentVanlaer
Copy link
Contributor

I think that the best way to solve this, is to have the layout mark outputs as gone and have the compositor deal with them in a callback. This way we don't have to make assumptions on what the "best" behavior should be. This callback could be the change event or something new. The latter allows the compositor to inspect the layout before it is sent to clients through xdg-ouput.

@VincentVanlaer
Copy link
Contributor

Looking at the code, it seems to me that the compositor already has the chance to react to an output being destroyed trough the events.destroy signal. The way wlr_output_layout_output uses wlr_outputmakes it also not that great to deal with layout outputs that are not connected to real outputs.

If library users want something like placeholder outputs, say for #479 or in general for not changing the layout when outputs disappear, it makes more sense that the extra state is kept in the compositor. If there's demand we could rewrite parts of wlr_output_layout, but that is definitely not part of this issue.

VincentVanlaer added a commit to VincentVanlaer/wlroots that referenced this issue May 26, 2018
An output that is made relative to another output will appear on one of
the borders of the parent output. Which border the outputs attaches to
can be configured. An exception to this is the SAME_AS configuration.
In this case child output is positioned at the same location as the
parent output. When the parent output changes position, the child
oututs will follow in order to maintain teh same relative position.

Relative outputs may overlap depending on the configuration. While the
original issue had detection of overlapping outputs as a feature, this
better fits in the compositor, since the library would have to make
assumptions about the wanted behavior.

When an ouput is removed and is a parent of another output, the child
output is fixed at its current position. If the compositor requires
different behaviour it can do this in response to the destroy call.

Made add_auto choose a location for the output and then fix the output
at that position. The previous behavior is prescriptive of how
compositors should handle their outputs and it is order dependent. As
this is most likely to be of use in examples, the new behavior is good
enough.

Fixes swaywm#550
VincentVanlaer added a commit to VincentVanlaer/wlroots that referenced this issue May 28, 2018
An output that is made relative to another output will appear on one of
the borders of the parent output. Which border the outputs attaches to
can be configured. An exception to this is the SAME_AS configuration.
In this case child output is positioned at the same location as the
parent output. When the parent output changes position, the child
oututs will follow in order to maintain teh same relative position.

Relative outputs may overlap depending on the configuration. While the
original issue had detection of overlapping outputs as a feature, this
better fits in the compositor, since the library would have to make
assumptions about the wanted behavior. An implementation for rootston
can be found in later commits.

When an ouput is removed and is a parent of another output, the child
output is fixed at its current position. If the compositor requires
different behaviour it can do this in response to the destroy signal.

Fixes swaywm#550
VincentVanlaer added a commit to VincentVanlaer/wlroots that referenced this issue Jun 2, 2018
An output that is made relative to another output will appear on one of
the borders of the parent output. Which border the outputs attaches to
can be configured. An exception to this is the SAME_AS configuration.
In this case child output is positioned at the same location as the
parent output. When the parent output changes position, the child
oututs will follow in order to maintain teh same relative position.

Relative outputs may overlap depending on the configuration. While the
original issue had detection of overlapping outputs as a feature, this
better fits in the compositor, since the library would have to make
assumptions about the wanted behavior. An implementation for rootston
can be found in later commits.

When an ouput is removed and is a parent of another output, the child
output is fixed at its current position. If the compositor requires
different behaviour it can do this in response to the destroy signal.

Fixes swaywm#550
@VincentVanlaer
Copy link
Contributor

This issue should be closed. It's

  • complicated to implement,
  • is prescriptive of what the compositor should do or support,
  • is better of living in the compositor or a separate client.

Having a standardized protocol for changing output positions would allow a client to manage layouts work on many compositors. This would also make it easy for most compositors to support complex layouts.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

3 participants