Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 0 additions & 173 deletions src/InternalUtils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -91,179 +91,6 @@ namespace Gala {
workspace_manager.thaw_remove ();
}

// Code ported from KWin present windows effect
// https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp

// some math utilities
private static int squared_distance (Gdk.Point a, Gdk.Point b) {
var k1 = b.x - a.x;
var k2 = b.y - a.y;

return k1 * k1 + k2 * k2;
}

private static Mtk.Rectangle rect_adjusted (Mtk.Rectangle rect, int dx1, int dy1, int dx2, int dy2) {
return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)};
}

private static Gdk.Point rect_center (Mtk.Rectangle rect) {
return {rect.x + rect.width / 2, rect.y + rect.height / 2};
}

public struct TilableWindow {
Mtk.Rectangle rect;
unowned WindowClone id;
}

/**
* Careful: List<TilableWindow?> windows will be modified in place and shouldn't be used afterwards.
*/
public static List<TilableWindow?> calculate_grid_placement (Mtk.Rectangle area, List<TilableWindow?> windows) {
uint window_count = windows.length ();
int columns = (int)Math.ceil (Math.sqrt (window_count));
int rows = (int)Math.ceil (window_count / (double)columns);

// Assign slots
int slot_width = area.width / columns;
int slot_height = area.height / rows;

TilableWindow?[] taken_slots = {};
taken_slots.resize (rows * columns);

// precalculate all slot centers
Gdk.Point[] slot_centers = {};
slot_centers.resize (rows * columns);
for (int x = 0; x < columns; x++) {
for (int y = 0; y < rows; y++) {
slot_centers[x + y * columns] = {
area.x + slot_width * x + slot_width / 2,
area.y + slot_height * y + slot_height / 2
};
}
}

// Assign each window to the closest available slot
while (windows.length () > 0) {
unowned List<TilableWindow?> link = windows.nth (0);
var window = link.data;
var rect = window.rect;

var slot_candidate = -1;
var slot_candidate_distance = int.MAX;
var pos = rect_center (rect);

// all slots
for (int i = 0; i < columns * rows; i++) {
if (i > window_count - 1)
break;

var dist = squared_distance (pos, slot_centers[i]);

if (dist < slot_candidate_distance) {
// window is interested in this slot
var occupier = taken_slots[i];
if (occupier == window)
continue;

if (occupier == null || dist < squared_distance (rect_center (occupier.rect), slot_centers[i])) {
// either nobody lives here, or we're better - takeover the slot if it's our best
slot_candidate = i;
slot_candidate_distance = dist;
}
}
}

if (slot_candidate == -1)
continue;

if (taken_slots[slot_candidate] != null)
windows.prepend (taken_slots[slot_candidate]);

windows.remove_link (link);
taken_slots[slot_candidate] = window;
}

var result = new List<TilableWindow?> ();

// see how many windows we have on the last row
int left_over = (int)window_count - columns * (rows - 1);

for (int slot = 0; slot < columns * rows; slot++) {
var window = taken_slots[slot];
// some slots might be empty
if (window == null)
continue;

var rect = window.rect;

// Work out where the slot is
Mtk.Rectangle target = {
area.x + (slot % columns) * slot_width,
area.y + (slot / columns) * slot_height,
slot_width,
slot_height
};
target = rect_adjusted (target, 10, 10, -10, -10);

float scale;
if (target.width / (double)rect.width < target.height / (double)rect.height) {
// Center vertically
scale = target.width / (float)rect.width;
target.y += (target.height - (int)(rect.height * scale)) / 2;
target.height = (int)Math.floorf (rect.height * scale);
} else {
// Center horizontally
scale = target.height / (float)rect.height;
target.x += (target.width - (int)(rect.width * scale)) / 2;
target.width = (int)Math.floorf (rect.width * scale);
}

// Don't scale the windows too much
if (scale > 1.0) {
scale = 1.0f;
target = {rect_center (target).x - (int)Math.floorf (rect.width * scale) / 2,
rect_center (target).y - (int)Math.floorf (rect.height * scale) / 2,
(int)Math.floorf (scale * rect.width),
(int)Math.floorf (scale * rect.height)};
}

// put the last row in the center, if necessary
if (left_over != columns && slot >= columns * (rows - 1))
target.x += (columns - left_over) * slot_width / 2;

result.prepend ({ target, window.id });
}

result.reverse ();
return result;
}

/*
* Sorts the windows by stacking order so that the window on active workspaces come first.
*/
public static SList<weak Meta.Window> sort_windows (Meta.Display display, List<Meta.Window> windows) {
var windows_on_active_workspace = new SList<Meta.Window> ();
var windows_on_other_workspaces = new SList<Meta.Window> ();
unowned var active_workspace = display.get_workspace_manager ().get_active_workspace ();
foreach (unowned var window in windows) {
if (window.get_workspace () == active_workspace) {
windows_on_active_workspace.append (window);
} else {
windows_on_other_workspaces.append (window);
}
}

var sorted_windows = new SList<weak Meta.Window> ();
var windows_on_active_workspace_sorted = display.sort_windows_by_stacking (windows_on_active_workspace);
windows_on_active_workspace_sorted.reverse ();
var windows_on_other_workspaces_sorted = display.sort_windows_by_stacking (windows_on_other_workspaces);
windows_on_other_workspaces_sorted.reverse ();
sorted_windows.concat ((owned) windows_on_active_workspace_sorted);
sorted_windows.concat ((owned) windows_on_other_workspaces_sorted);

return sorted_windows;
}

public static inline bool get_window_is_normal (Meta.Window window) {
switch (window.window_type) {
case Meta.WindowType.NORMAL:
Expand Down
Loading