elementary / wingpanel

Stylish top panel that holds indicators and spawns an application launcher
https://elementary.io
GNU General Public License v3.0
135 stars 46 forks source link

Fix: Cannot move windows to secondary display above panel #235

Closed felix-andreas closed 4 years ago

felix-andreas commented 5 years ago

Fixes: #33 , https://github.com/elementary/gala/issues/7

To my understanding this issue is not in Gala or Mutter! I think, the problem are the struts of the wingpanel (as stated in https://github.com/elementary/wingpanel/issues/33).

Specification: freedesktop.org defines the specifaction _NET_WM_STRUT_PARTIAL which clients can use to reserve space at the edge of the screen. The Window Manager then reduces the WORKSPACE_AREA by this indicated area.

Wingpanel code:

var position_top = monitor_y - panel_displacement;

long struts[12];

this.screen.get_monitor_geometry (monitor, out primary_monitor_rect);

// We need to manually include the scale factor here as GTK gives us unscaled sizes for widgets
struts = { 0, 0, position_top * scale_factor, 0, /* strut-left, strut-right, strut-top, strut-bottom */
           0, 0, /* strut-left-start-y, strut-left-end-y */
           0, 0, /* strut-right-start-y, strut-right-end-y */
           monitor_x, ((monitor_x + monitor_width) * scale_factor) - 1, /* strut-top-start-x, strut-top-end-x */
           0, 0 }; /* strut-bottom-start-x, strut-bottom-end-x */

As one can see the wingpanel is actually reserving ALL space above the bottom edge of panel. Therefore it is not possible to move a window above the wingpanel.

Visualization: current_vertical_reserve Solid dark lines: Monitors, Blue area: area that client reserves. Dotted area: screen area

A problem is that, the _NET_WM_STRUCT_PARTICAL specification is limited in that way that it does not allow to reserve space for arbitrary rectangles. Instead it only allows to reserve space at the borders of screen area (which is the sum of all monitor areas). As for multi-monitor layouts the wingpanel can also be within this screen area (and not at the border) this makes it impossible to reserve the correct space for all possible multi-monitor layouts.

One Solution: Fortunately for up to 3 monitors it is always a possible to reserve the correct space by also using the struct-left and struct-right cardinals as shown in this example:

multi_monitor

Solid dark lines: Monitors, Blue area: area that client reserves. Dotted area: screen area

For setups where the primary monitor has a left, right and top neighbor (example with ❌) I think there is no way one can use this specification to reserve the correct area. I think in this case it is the best to reserve no space at all.

felix-andreas commented 5 years ago

I am not 100% sure if this already works for all scale_factors. I will revise the logic within the next few days.

felix-andreas commented 5 years ago

I think this now also works with scale_factor different than one!

Is it possible to have to have different scale_factors for different monitors? If this is the case then the functions which check if another monitor is to the left/right or above have to be adjusted. If not this is ready for review!

felix-andreas commented 4 years ago

@kgrubb , I have seen you have updated this branch twice. Would you maybe have time to take a look/review this branch?

felix-andreas commented 4 years ago

I have not been able to test the case with a display above and next to the primary; does this branch attempt to address that?

@cassidyjames Yes! Moreover this branch should work with all layouts for up to 3 monitors. For 4 and more monitors it should work if the primary monitor has at least one open side (i.e. it has no left, no upper or no right neighbor) (see example 3 and example 4 with the ✔️).

To my understanding it is not possible to use the current _NET_WM_STRUT_PARTIAL specification to set the wingpanel structs correctly if the primary monitor has a left, upper and right neighbor at the same time(see example with ❌️). I think this would need a new freedesktop.org specification which has to be implemented in mutter...

cassidyjames commented 4 years ago

@andreasfelix could we address that case here by just dropping all struts when there are displays on that many sides? Mutter still has the window edge snapping when moving near the panel, so a strut wouldn't be strictly necessary in that sort of setup.

felix-andreas commented 4 years ago

Plank has currently the same problem. This logic should also be implemented there.