Cleanup natural_placement

This commit is contained in:
Tom Beckmann 2012-08-25 01:01:48 +02:00
parent bcbc38413f
commit 7dae5e002e

View File

@ -74,7 +74,6 @@ namespace Gala
const int ACCURACY = 1; const int ACCURACY = 1;
const int BORDER = 10; const int BORDER = 10;
const int TOP_GAP = 20; const int TOP_GAP = 20;
const bool use_more_screen = false;
struct Point struct Point
{ {
@ -98,17 +97,19 @@ namespace Gala
{ {
var k1 = b.x - a.x; var k1 = b.x - a.x;
var k2 = b.y - a.y; var k2 = b.y - a.y;
return Math.sqrtf (k1*k1 + k2*k2);
return k1*k1 + k2*k2;
} }
void calculate_places (List<Actor> windows) void calculate_places (List<Actor> windows)
{ {
var clones = windows.copy (); var clones = windows.copy ();
clones.sort ((a, b) => { clones.sort ((a, b) => {
return (int)(a as ExposedWindow).window.get_stable_sequence () - (int)(b as ExposedWindow).window.get_stable_sequence (); return (int)(a as ExposedWindow).window.get_stable_sequence () -
(int)(b as ExposedWindow).window.get_stable_sequence ();
}); });
// Put a gap on the right edge of the workspace to separe it from the workspace selector // get the area used by the expo algorithms together
var geom = screen.get_monitor_geometry (screen.get_primary_monitor ()); var geom = screen.get_monitor_geometry (screen.get_primary_monitor ());
var ratio = geom.width / (float)geom.height; var ratio = geom.width / (float)geom.height;
var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio);
@ -156,11 +157,12 @@ namespace Gala
// precalculate all slot centers // precalculate all slot centers
Point[] slot_centers = {}; Point[] slot_centers = {};
slot_centers.resize (rows * columns); slot_centers.resize (rows * columns);
for (int x = 0; x < columns; x++) for (int x = 0; x < columns; x++) {
for (int y = 0; y < rows; y++) { for (int y = 0; y < rows; y++) {
slot_centers[x + y*columns] = {area.x + slot_width * x + slot_width / 2, slot_centers[x + y*columns] = {area.x + slot_width * x + slot_width / 2,
area.y + slot_height * y + slot_height / 2}; area.y + slot_height * y + slot_height / 2};
} }
}
// Assign each window to the closest available slot // Assign each window to the closest available slot
var tmplist = clones.copy (); // use a QLinkedList copy instead? var tmplist = clones.copy (); // use a QLinkedList copy instead?
@ -236,15 +238,17 @@ namespace Gala
var direction = 0; var direction = 0;
var directions = new List<int> (); var directions = new List<int> ();
var rects = new List<Meta.Rectangle?> (); var rects = new List<Meta.Rectangle?> ();
for (var i = 0; i < clones.length (); i++) { for (var i = 0; i < clones.length (); i++) {
// save rectangles into 4-dimensional arrays representing two corners of the rectangular: [left_x, top_y, right_x, bottom_y] // save rectangles into 4-dimensional arrays representing two corners of the rectangular: [left_x, top_y, right_x, bottom_y]
var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect ();
rects.append ({rect.x, rect.y, rect.width, rect.height}); rects.append ({rect.x, rect.y, rect.width, rect.height});
bounds = bounds.union (rects.nth_data (i)); bounds = bounds.union (rects.nth_data (i));
// This is used when the window is on the edge of the screen to try to use as much screen real estate as possible. // This is used when the window is on the edge of the screen to try to use as much screen real estate as possible.
directions.append (direction); directions.append (direction);
direction ++; direction++;
if (direction == 4) { if (direction == 4) {
direction = 0; direction = 0;
} }
@ -256,88 +260,88 @@ namespace Gala
overlap = false; overlap = false;
for (var i = 0; i < rects.length (); i++) { for (var i = 0; i < rects.length (); i++) {
for (var j = 0; j < rects.length (); j++) { for (var j = 0; j < rects.length (); j++) {
if (i != j && rect_adjusted(rects.nth_data (i), -GAPS, -GAPS, GAPS, GAPS).overlap (
rect_adjusted (rects.nth_data (j), -GAPS, -GAPS, GAPS, GAPS))) { var rect = rects.nth_data (i);
loop_counter ++; var comp = rects.nth_data (j);
overlap = true;
if (i == j || rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap (
// Determine pushing direction rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS)))
Point i_center = rect_center (rects.nth_data (i)); continue;
Point j_center = rect_center (rects.nth_data (j));
Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; loop_counter ++;
overlap = true;
// Prevent dividing by zero and non-movement
if (diff.x == 0 && diff.y == 0) // Determine pushing direction
diff.x = 1; Point i_center = rect_center (rect);
// Try to keep screen/workspace aspect ratio Point j_center = rect_center (comp);
if (bounds.height / bounds.width > area.height / area.width) Point diff = {j_center.x - i_center.x, j_center.y - i_center.y};
diff.x *= 2;
else // Prevent dividing by zero and non-movement
diff.y *= 2; if (diff.x == 0 && diff.y == 0)
diff.x = 1;
// Approximate a vector of between 10px and 20px in magnitude in the same direction // Try to keep screen/workspace aspect ratio
var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y); if (bounds.height / bounds.width > area.height / area.width)
diff.x = (int)Math.floorf (diff.x * ACCURACY / length); diff.x *= 2;
diff.y = (int)Math.floorf (diff.y * ACCURACY / length); else
diff.y *= 2;
// Move both windows apart
rects.nth_data (i).x += -diff.x; // Approximate a vector of between 10px and 20px in magnitude in the same direction
rects.nth_data (i).y += -diff.y; var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y);
rects.nth_data (j).x += diff.x; diff.x = (int)Math.floorf (diff.x * ACCURACY / length);
rects.nth_data (j).y += diff.y; diff.y = (int)Math.floorf (diff.y * ACCURACY / length);
// Move both windows apart
if (use_more_screen) { rect = rect_translate (rect, -diff.x, -diff.y);
// Try to keep the bounding rect the same aspect as the screen so that more comp = rect_translate (comp, diff.x, diff.y);
// screen real estate is utilised. We do this by splitting the screen into nine
// equal sections, if the window center is in any of the corner sections pull the // Try to keep the bounding rect the same aspect as the screen so that more
// window towards the outer corner. If it is in any of the other edge sections // screen real estate is utilised. We do this by splitting the screen into nine
// alternate between each corner on that edge. We don't want to determine it // equal sections, if the window center is in any of the corner sections pull the
// randomly as it will not produce consistant locations when using the filter. // window towards the outer corner. If it is in any of the other edge sections
// Only move one window so we don't cause large amounts of unnecessary zooming // alternate between each corner on that edge. We don't want to determine it
// in some situations. We need to do this even when expanding later just in case // randomly as it will not produce consistant locations when using the filter.
// all windows are the same size. // Only move one window so we don't cause large amounts of unnecessary zooming
// (We are using an old bounding rect for this, hopefully it doesn't matter) // in some situations. We need to do this even when expanding later just in case
var x_section = Math.roundf ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); // all windows are the same size.
var y_section = Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); // (We are using an old bounding rect for this, hopefully it doesn't matter)
var x_section = (int)Math.roundf ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f));
i_center = rect_center (rects.nth_data (i)); var y_section = (int)Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f));
diff.x = 0;
diff.y = 0; i_center = rect_center (rect);
if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well diff.x = 0;
if (x_section == 1) diff.y = 0;
x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well
if (y_section == 1) if (x_section == 1)
y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0);
} if (y_section == 1)
if (x_section == 0 && y_section == 0) { y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0);
diff.x = bounds.x - i_center.x;
diff.y = bounds.y - i_center.y;
}
if (x_section == 2 && y_section == 0) {
diff.x = bounds.x + bounds.width - i_center.x;
diff.y = bounds.y - i_center.y;
}
if (x_section == 2 && y_section == 2) {
diff.x = bounds.x + bounds.width - i_center.x;
diff.y = bounds.y + bounds.height - i_center.y;
}
if (x_section == 0 && y_section == 2) {
diff.x = bounds.x - i_center.x;
diff.y = bounds.y + bounds.height - i_center.y;
}
if (diff.x != 0 || diff.y != 0) {
length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y);
diff.x *= (int)Math.floorf (ACCURACY / length / 2.0f);
diff.y *= (int)Math.floorf (ACCURACY / length / 2.0f);
rects.nth_data (i).x += diff.x;
rects.nth_data (i).y += diff.y;
}
}
// Update bounding rect
bounds = bounds.union(rects.nth_data (i));
bounds = bounds.union(rects.nth_data (j));
} }
if (x_section == 0 && y_section == 0) {
diff.x = bounds.x - i_center.x;
diff.y = bounds.y - i_center.y;
}
if (x_section == 2 && y_section == 0) {
diff.x = bounds.x + bounds.width - i_center.x;
diff.y = bounds.y - i_center.y;
}
if (x_section == 2 && y_section == 2) {
diff.x = bounds.x + bounds.width - i_center.x;
diff.y = bounds.y + bounds.height - i_center.y;
}
if (x_section == 0 && y_section == 2) {
diff.x = bounds.x - i_center.x;
diff.y = bounds.y + bounds.height - i_center.y;
}
if (diff.x != 0 || diff.y != 0) {
length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y);
diff.x *= (int)Math.floorf (ACCURACY / length / 2.0f);
diff.y *= (int)Math.floorf (ACCURACY / length / 2.0f);
rect.x += diff.x;
rect.y += diff.y;
}
// Update bounding rect
bounds = bounds.union(rect);
bounds = bounds.union(comp);
} }
} }
} while (overlap && loop_counter < MAX_TRANSLATIONS); } while (overlap && loop_counter < MAX_TRANSLATIONS);
@ -352,16 +356,17 @@ namespace Gala
bounds.height = (int)Math.floorf (area.height / scale); bounds.height = (int)Math.floorf (area.height / scale);
// Move all windows back onto the screen and set their scale // Move all windows back onto the screen and set their scale
for (var i = 0; i < rects.length (); i++) { var index = 0;
rects.nth_data (i).x += -bounds.x; foreach (var rect in rects) {
rects.nth_data (i).y += -bounds.y; rect = rect_translate (rect, -bounds.x, -bounds.y);
rects.nth_data (i).x = (int)Math.floorf (rects.nth_data (i).x * scale + area.x); rect = {(int)Math.floorf (rect.x * scale + area.x),
rects.nth_data (i).y = (int)Math.floorf (rects.nth_data (i).y * scale + area.y); (int)Math.floorf (rect.y * scale + area.y),
rects.nth_data (i).width = (int)Math.floorf (rects.nth_data (i).width * scale); (int)Math.floorf (rect.width * scale),
rects.nth_data (i).height = (int)Math.floorf (rects.nth_data (i).height * scale); (int)Math.floorf (rect.height * scale)};
place_window (clones.nth_data (i) as ExposedWindow, rects.nth_data (i)); place_window (clones.nth_data (index) as ExposedWindow, rect);
index++;
} }
} }
@ -379,9 +384,6 @@ namespace Gala
var used_windows = new SList<Window> (); var used_windows = new SList<Window> ();
Compositor.get_background_actor_for_screen (screen).
animate (AnimationMode.EASE_OUT_QUAD, 1000, dim_factor : 0.4);
foreach (var window in screen.get_active_workspace ().list_windows ()) { foreach (var window in screen.get_active_workspace ().list_windows ()) {
if (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DOCK) { if (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DOCK) {
(window.get_compositor_private () as Actor).hide (); (window.get_compositor_private () as Actor).hide ();
@ -397,6 +399,9 @@ namespace Gala
if (n_windows == 0) if (n_windows == 0)
return; return;
Compositor.get_background_actor_for_screen (screen).
animate (AnimationMode.EASE_OUT_QUAD, 1000, dim_factor : 0.4);
// sort windows by stacking order // sort windows by stacking order
var windows = screen.get_display ().sort_windows_by_stacking (used_windows); var windows = screen.get_display ().sort_windows_by_stacking (used_windows);
@ -426,6 +431,7 @@ namespace Gala
calculate_places (get_children ()); calculate_places (get_children ());
} }
//called when a window has been closed
void reposition (ExposedWindow removed) void reposition (ExposedWindow removed)
{ {
var children = get_children ().copy (); var children = get_children ().copy ();