Skip to content

Commit b8aa4aa

Browse files
committed
Don't spread in multitasking view unless there are stacking windows
1 parent 15c670d commit b8aa4aa

File tree

5 files changed

+98
-18
lines changed

5 files changed

+98
-18
lines changed

src/Widgets/MultitaskingView/MonitorClone.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class Gala.MonitorClone : ActorTarget {
3535

3636
var windows = new WindowListModel (display, STACKING, true, monitor);
3737

38-
window_container = new WindowCloneContainer (wm, windows, monitor_scale);
38+
window_container = new WindowCloneContainer (wm, windows, monitor, monitor_scale);
3939
window_container.add_constraint (new Clutter.BindConstraint (this, SIZE, 0.0f));
4040
window_container.window_selected.connect ((w) => { window_selected (w); });
4141
bind_property ("monitor-scale", window_container, "monitor-scale");

src/Widgets/MultitaskingView/WindowCloneContainer.vala

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class Gala.WindowCloneContainer : ActorTarget {
1818

1919
public WindowManager wm { get; construct; }
2020
public WindowListModel windows { get; construct; }
21+
public int monitor { get; construct; }
2122
public float monitor_scale { get; construct set; }
2223
public bool overview_mode { get; construct; }
2324

@@ -29,8 +30,8 @@ public class Gala.WindowCloneContainer : ActorTarget {
2930
*/
3031
private unowned WindowClone? current_window = null;
3132

32-
public WindowCloneContainer (WindowManager wm, WindowListModel windows, float monitor_scale, bool overview_mode = false) {
33-
Object (wm: wm, windows: windows, monitor_scale: monitor_scale, overview_mode: overview_mode);
33+
public WindowCloneContainer (WindowManager wm, WindowListModel windows, int monitor, float monitor_scale, bool overview_mode = false) {
34+
Object (wm: wm, windows: windows, monitor: monitor, monitor_scale: monitor_scale, overview_mode: overview_mode);
3435
}
3536

3637
construct {
@@ -140,14 +141,7 @@ public class Gala.WindowCloneContainer : ActorTarget {
140141
return (int) (seq_b - seq_a);
141142
});
142143

143-
Mtk.Rectangle area = {
144-
padding_left,
145-
padding_top,
146-
(int) width - padding_left - padding_right,
147-
(int) height - padding_top - padding_bottom
148-
};
149-
150-
foreach (var tilable in calculate_grid_placement (area, windows)) {
144+
foreach (var tilable in calculate_window_clones_placement (windows)) {
151145
tilable.clone.take_slot (tilable.rect, !view_toggle);
152146
}
153147
}
@@ -322,10 +316,95 @@ public class Gala.WindowCloneContainer : ActorTarget {
322316
Mtk.Rectangle rect;
323317
}
324318

319+
private bool windows_overlap (GLib.List<TilableWindow?> windows) {
320+
var checked_rects = new GLib.List<Mtk.Rectangle?> ();
321+
foreach (var tilable in windows) {
322+
var window_rect = tilable.clone.window.get_frame_rect ();
323+
foreach (var checked_rect in checked_rects) {
324+
if (window_rect.overlap (checked_rect)) {
325+
return true;
326+
}
327+
}
328+
329+
checked_rects.append (window_rect);
330+
}
331+
332+
return false;
333+
}
334+
335+
private bool window_out_of_screen (GLib.List<TilableWindow?> windows) {
336+
foreach (var tilable in windows) {
337+
unowned var window = tilable.clone.window;
338+
var window_rect = window.get_frame_rect ();
339+
var monitor_geometry = window.display.get_monitor_geometry (window.get_monitor ());
340+
if (window_rect.x < monitor_geometry.x ||
341+
window_rect.y < monitor_geometry.y ||
342+
window_rect.x + window_rect.width > monitor_geometry.width ||
343+
window_rect.y + window_rect.height > monitor_geometry.height
344+
) {
345+
return true;
346+
}
347+
}
348+
349+
return false;
350+
}
351+
352+
private Mtk.Rectangle get_rectangle_with_padding () {
353+
return {
354+
padding_left,
355+
padding_top,
356+
(int) width - padding_left - padding_right,
357+
(int) height - padding_top - padding_bottom
358+
};
359+
}
360+
361+
private GLib.List<TilableWindow?> calculate_window_clones_placement (GLib.List<TilableWindow?> windows) {
362+
if (windows_overlap (windows) || window_out_of_screen (windows)) {
363+
return calculate_grid_placement (windows);
364+
} else {
365+
Mtk.Rectangle area;
366+
if (overview_mode) {
367+
area = { 0, 0, (int) width, (int) height };
368+
} else {
369+
area = get_rectangle_with_padding ();
370+
}
371+
372+
var monitor_geometry = wm.get_display ().get_monitor_geometry (monitor);
373+
var scale = (float) area.width / monitor_geometry.width;
374+
375+
var result = new GLib.List<TilableWindow?> ();
376+
foreach (var tilable in windows) {
377+
Mtk.Rectangle rect;
378+
#if HAS_MUTTER46
379+
tilable.rect.scale_double (scale, Mtk.RoundingStrategy.ROUND, out rect);
380+
#else
381+
rect = {
382+
0,
383+
0,
384+
Utils.scale_to_int (tilable.rect.width, scale),
385+
Utils.scale_to_int (tilable.rect.height, scale)
386+
};
387+
#endif
388+
389+
var x_ratio = (float) tilable.rect.x / monitor_geometry.width;
390+
rect.x = area.x + Utils.scale_to_int (area.width, x_ratio);
391+
392+
var y_ratio = (float) tilable.rect.y / monitor_geometry.height;
393+
rect.y = area.y + Utils.scale_to_int (area.height, y_ratio);
394+
395+
result.append ({ tilable.clone, rect });
396+
}
397+
398+
return result;
399+
}
400+
}
401+
325402
/**
326403
* Careful: List<TilableWindow?> windows will be modified in place and shouldn't be used afterwards.
327404
*/
328-
private GLib.List<TilableWindow?> calculate_grid_placement (Mtk.Rectangle area, GLib.List<TilableWindow?> windows) {
405+
private GLib.List<TilableWindow?> calculate_grid_placement (GLib.List<TilableWindow?> windows) {
406+
var area = get_rectangle_with_padding ();
407+
329408
uint window_count = windows.length ();
330409
int columns = (int) Math.ceil (Math.sqrt (window_count));
331410
int rows = (int) Math.ceil (window_count / (double) columns);

src/Widgets/MultitaskingView/WorkspaceClone.vala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,17 @@ public class Gala.WorkspaceClone : ActorTarget {
137137

138138
construct {
139139
unowned var display = workspace.get_display ();
140-
var monitor_geometry = display.get_monitor_geometry (display.get_primary_monitor ());
140+
var primary_monitor = display.get_primary_monitor ();
141+
var monitor_geometry = display.get_monitor_geometry (primary_monitor);
141142

142143
var background_click_action = new Clutter.ClickAction ();
143144
background_click_action.clicked.connect (() => activate (true));
144145
background = new FramedBackground (display);
145146
background.add_action (background_click_action);
146147

147-
windows = new WindowListModel (display, STACKING, true, display.get_primary_monitor (), workspace);
148+
windows = new WindowListModel (display, STACKING, true, primary_monitor, workspace);
148149

149-
window_container = new WindowCloneContainer (wm, windows, monitor_scale) {
150+
window_container = new WindowCloneContainer (wm, windows, primary_monitor, monitor_scale) {
150151
width = monitor_geometry.width,
151152
height = monitor_geometry.height,
152153
};

src/Widgets/WindowOverview.vala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public class Gala.WindowOverview : ActorTarget, RootTarget, ActivatableComponent
119119
var model = new WindowListModel (display, STACKING, true, i, null, custom_filter);
120120
model.items_changed.connect (on_items_changed);
121121

122-
window_clone_container = new WindowCloneContainer (wm, model, scale, true) {
122+
window_clone_container = new WindowCloneContainer (wm, model, i, scale, true) {
123123
padding_top = TOP_GAP,
124124
padding_left = BORDER,
125125
padding_right = BORDER,
@@ -173,7 +173,7 @@ public class Gala.WindowOverview : ActorTarget, RootTarget, ActivatableComponent
173173

174174
private void on_items_changed (ListModel model, uint pos, uint removed, uint added) {
175175
// Check removed > added to make sure we only close once when the last window is removed
176-
// This avoids an inifinite loop since closing will sort the windows which also triggers this signal
176+
// This avoids an infinite loop since closing will sort the windows which also triggers this signal
177177
if (is_opened () && removed > added && model.get_n_items () == 0) {
178178
close ();
179179
}

vapi/mutter-mtk-13.vapi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ namespace Mtk {
8080
#endif
8181
public bool overlap (Mtk.Rectangle rect2);
8282
#if HAS_MUTTER46
83-
public void scale_double (double scale, Mtk.RoundingStrategy rounding_strategy, Mtk.Rectangle dest);
83+
public void scale_double (double scale, Mtk.RoundingStrategy rounding_strategy, out Mtk.Rectangle dest);
8484
#endif
8585
public Graphene.Rect? to_graphene_rect ();
8686
#if HAS_MUTTER47

0 commit comments

Comments
 (0)