From ed4f7ea61412d58548905463424631edaad24cc6 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Wed, 1 Aug 2012 22:42:52 +0200 Subject: [PATCH 01/46] Add expose feature --- CMakeLists.txt | 2 + data/org.pantheon.desktop.gala.gschema.xml | 6 + src/Expo.vala | 164 +++++++++++++++++++++ src/Plugin.vala | 13 +- src/Widgets/ExposedWindow.vala | 93 ++++++++++++ 5 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 src/Expo.vala create mode 100644 src/Widgets/ExposedWindow.vala diff --git a/CMakeLists.txt b/CMakeLists.txt index 42b4227a..a4da99ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,12 +48,14 @@ ensure_vala_version("0.16.0" MINIMUM) include(ValaPrecompile) vala_precompile(VALA_C src/DBus.vala + src/Expo.vala src/Main.vala src/Plugin.vala src/Settings.vala src/TextShadowEffect.vala src/Utils.vala src/Widgets/AppIcon.vala + src/Widgets/ExposedWindow.vala src/Widgets/WindowSwitcher.vala src/Widgets/WorkspaceThumb.vala src/Widgets/WorkspaceView.vala diff --git a/data/org.pantheon.desktop.gala.gschema.xml b/data/org.pantheon.desktop.gala.gschema.xml index e820770c..e162a816 100644 --- a/data/org.pantheon.desktop.gala.gschema.xml +++ b/data/org.pantheon.desktop.gala.gschema.xml @@ -7,6 +7,7 @@ + @@ -65,6 +66,11 @@ Shortcut to move to last workspace + + e']]]> + Shortcut to move to last workspace + + diff --git a/src/Expo.vala b/src/Expo.vala new file mode 100644 index 00000000..5f6f1d45 --- /dev/null +++ b/src/Expo.vala @@ -0,0 +1,164 @@ +using Meta; +using Clutter; + +namespace Gala +{ + public class Expo : Actor + { + + Plugin plugin; + Screen screen; + + public Expo (Plugin _plugin) + { + plugin = _plugin; + screen = plugin.get_screen (); + + screen.workspace_switched.connect (() => close (false) ); + + visible = false; + } + + //vala doesnt support multidimensional array of different sizes, that's why we fill them up with 0s + static float [,,] POSITIONS = { + {{0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{0.0f, 0.0f, 0.5f, 1.0f}, {0.5f, 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{0.0f, 0.0f, 0.5f, 0.5f}, {0.5f, 0.0f, 0.5f, 0.5f}, {0.0f, 0.5f, 1.0f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{0.0f, 0.0f, 0.5f, 0.5f}, {0.5f, 0.0f, 0.5f, 0.5f}, {0.0f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{0.0f, 0.0f, 0.3f, 0.5f}, {0.3f, 0.0f, 0.3f, 0.5f}, {0.6f, 0.0f, 0.3f, 0.5f}, {0.0f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{0.0f, 0.0f, 0.3f, 0.5f}, {0.3f, 0.0f, 0.3f, 0.5f}, {0.6f, 0.0f, 0.3f, 0.5f}, {0.0f, 0.5f, 0.3f, 0.5f}, {0.3f, 0.5f, 0.3f, 0.5f}, {0.6f, 0.5f, 0.3f, 0.5f}} + }; + + public void open (bool animate=true) + { + if (visible) + return; + + var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); + Meta.Rectangle workarea = {monitor.x + 50, monitor.y + 50, monitor.width - 100, monitor.height - 150}; + + var used_windows = new SList (); + + screen.get_active_workspace ().list_windows ().foreach ((w) => { + if (w.window_type != Meta.WindowType.NORMAL || w.minimized) + return; + used_windows.append (w); + }); + + var windows = screen.get_display ().sort_windows_by_stacking (used_windows); + + var n_windows = used_windows.length (); + if (n_windows == 0) + return; + + var rows = (int)Math.ceilf (Math.sqrtf (n_windows)); + var cols = (int)Math.ceilf (n_windows / (float)rows); + + plugin.begin_modal (); + Utils.set_input_area (screen, InputArea.FULLSCREEN); + + var i = 0; + windows.foreach ((w) => { + var actor = w.get_compositor_private () as WindowActor; + if (actor == null) + return; + actor.hide (); + + var clone = new ExposedWindow (w); + + clone.selected.connect (selected); + + clone.x = actor.x; + clone.y = actor.y; + + //calculate new rect + float scale_x = 1.0f; + float scale_y = 1.0f; + float dest_w = actor.width; + float dest_h = actor.height; + float dest_x, dest_y, max_width, max_height; + + visible = true; + + if (n_windows > POSITIONS.length[0]) { + max_width = workarea.width / cols - 50; + max_height = workarea.height / rows - 50; + + dest_x = workarea.x + workarea.width * ((i % rows) / (float)rows); + dest_y = workarea.y + workarea.height * Math.floorf ((i / (float)rows)) / (float)cols; + } else { + max_width = workarea.width * POSITIONS[n_windows-1,i,2] - 50; + max_height = workarea.height * POSITIONS[n_windows-1,i,3] - 50; + + dest_x = workarea.x + workarea.width * POSITIONS[n_windows-1,i,0]; + dest_y = workarea.y + workarea.height * POSITIONS[n_windows-1,i,1]; + } + + if (dest_w > max_width || dest_h > max_height) { + var aspect = (max_width / dest_w < max_height / dest_h) ? max_width / dest_w : max_height / dest_h; + dest_w = dest_w * aspect; + dest_h = dest_h * aspect; + scale_x = (dest_w) / actor.width; + scale_y = (dest_h) / actor.height; + } + + dest_x += max_width / 2 - dest_w / 2; //center them + dest_y += max_height / 2 - dest_h / 2; + + if (animate) { + clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, + scale_x:scale_x, scale_y:scale_y, x:dest_x, y:dest_y).completed.connect (() => { + + clone.icon.x = clone.x + (clone.width * scale_x) / 2 - clone.icon.width/2; + clone.icon.y = clone.y + clone.height*scale_y - 30; + clone.icon.raise_top (); + clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 150, scale_x:1.0f, scale_y:1.0f); + }); + } else { + clone.scale_x = scale_x; + clone.scale_y = scale_y; + clone.x = dest_x; + clone.y = dest_y; + + clone.icon.x = clone.x + (clone.width * scale_x) / 2 - clone.icon.width/2; + clone.icon.y = clone.y + clone.height*scale_y - 30; + clone.icon.raise_top (); + clone.icon.scale_x = 1.0f; + clone.icon.scale_y = 1.0f; + } + + add_child (clone); + + i ++; + }); + } + + void selected (Window window) + { + window.activate (screen.get_display ().get_current_time ()); + + close (true); + } + + void close (bool animate = true) + { + plugin.end_modal (); + plugin.update_input_area (); + + get_children ().foreach ( (c) => { + var exposed = c as ExposedWindow; + exposed.close (animate); + exposed.selected.disconnect (selected); + }); + + if (animate) { + Timeout.add (250, () => { + visible = false; + return false; + }); + } else { + visible = false; + } + } + } +} diff --git a/src/Plugin.vala b/src/Plugin.vala index d431c940..8969af25 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -26,7 +26,8 @@ namespace Gala MAXIMIZE_CURRENT, MINIMIZE_CURRENT, OPEN_LAUNCHER, - CUSTOM_COMMAND + CUSTOM_COMMAND, + EXPOSE } public enum InputArea { @@ -39,6 +40,7 @@ namespace Gala { WindowSwitcher winswitcher; WorkspaceView workspace_view; + Expo expo; Window? moving; //place for the window that is being moved over @@ -77,11 +79,17 @@ namespace Gala winswitcher = new WindowSwitcher (this); + expo = new Expo (this); + stage.add_child (workspace_view); stage.add_child (winswitcher); + stage.add_child (expo); /*keybindings*/ + screen.get_display ().add_keybinding ("expose-windows", BehaviorSettings.get_default ().schema, 0, () => { + expo.open (true); + }); screen.get_display ().add_keybinding ("move-to-workspace-first", BehaviorSettings.get_default ().schema, 0, () => { screen.get_workspace_by_index (0).activate (screen.get_display ().get_current_time ()); }); @@ -279,6 +287,9 @@ namespace Gala warning (e.message); } break; + case ActionType.EXPOSE: + expo.open (true); + break; default: warning ("Trying to run unknown action"); break; diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala new file mode 100644 index 00000000..a893f57b --- /dev/null +++ b/src/Widgets/ExposedWindow.vala @@ -0,0 +1,93 @@ +// +// Copyright (C) 2012 Tom Beckmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using Meta; + +namespace Gala +{ + public class ExposedWindow : Clutter.Group + { + public weak Window window; + Clutter.Clone clone; + public GtkClutter.Texture icon; + + public signal void selected (Window window); + + public ExposedWindow (Window _window) + { + window = _window; + + var actor = _window.get_compositor_private () as WindowActor; + clone = new Clutter.Clone (actor.get_texture ()); + + reactive = true; + + icon = new GtkClutter.Texture (); + icon.scale_x = 0.0f; + icon.scale_y = 0.0f; + icon.scale_gravity = Clutter.Gravity.CENTER; + try { + icon.set_from_pixbuf (Utils.get_icon_for_window (window, 64)); + } catch (Error e) { warning (e.message); } + + add_child (clone); + + Compositor.get_stage_for_screen (window.get_screen ()).add_child (icon); + } + + public override bool button_press_event (Clutter.ButtonEvent event) + { + raise_top (); + selected (window); + + return true; + } + + public void close (bool do_animate=true) + { + unowned Rectangle rect = window.get_outer_rect (); + + //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized windows + float delta = (window.maximized_horizontally || window.maximized_vertically)?0:10; + + float dest_x = rect.x - delta; + float dest_y = rect.y - delta; + + icon.animate (Clutter.AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f) + .completed.connect ( () => { + icon.destroy (); + }); + + if (do_animate) { + animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, + scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { + + (window.get_compositor_private () as Clutter.Actor).show (); + destroy (); + }); + } else { + scale_x = 1.0f; + scale_y = 1.0f; + x = dest_x; + y = dest_y; + + (window.get_compositor_private () as Clutter.Actor).show (); + destroy (); + } + } + } +} From 9a61a85227551d2390a291db6ab73b035e747b5e Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Wed, 1 Aug 2012 22:48:26 +0200 Subject: [PATCH 02/46] Make it togglable from hotcorner --- src/Expo.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Expo.vala b/src/Expo.vala index 5f6f1d45..46490995 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -31,8 +31,10 @@ namespace Gala public void open (bool animate=true) { - if (visible) + if (visible) { + close (); return; + } var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); Meta.Rectangle workarea = {monitor.x + 50, monitor.y + 50, monitor.width - 100, monitor.height - 150}; From 9f763e1be7885439f834bfbd9bd9e73c6fdaafca Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 3 Aug 2012 00:09:27 +0200 Subject: [PATCH 03/46] Fixed unexpected and buggy behavior, added a copyright header --- src/Expo.vala | 76 ++++++++++++++++++++++++++++------ src/Widgets/ExposedWindow.vala | 6 ++- src/Widgets/WorkspaceView.vala | 6 +-- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 46490995..066b6f72 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -1,3 +1,20 @@ +// +// Copyright (C) 2012 Tom Beckmann +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + using Meta; using Clutter; @@ -9,6 +26,8 @@ namespace Gala Plugin plugin; Screen screen; + bool ready; + public Expo (Plugin _plugin) { plugin = _plugin; @@ -17,9 +36,27 @@ namespace Gala screen.workspace_switched.connect (() => close (false) ); visible = false; + ready = true; } - //vala doesnt support multidimensional array of different sizes, that's why we fill them up with 0s + public override bool key_press_event (Clutter.KeyEvent event) + { + //FIXME need to figure out the actual keycombo, for now leave it by default and others will close it by selecting a window! + if (event.keyval == Clutter.Key.e) { + close (true); + + return true; + } + + return false; + } + + public override void key_focus_out () + { + close (false); + } + + //vala doesnt support multidimensional array of different sizes, that's why we fill them up with 0s static float [,,] POSITIONS = { {{0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, {{0.0f, 0.0f, 0.5f, 1.0f}, {0.5f, 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, @@ -31,11 +68,16 @@ namespace Gala public void open (bool animate=true) { + if (!ready) + return; + if (visible) { close (); return; } + ready = false; + var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); Meta.Rectangle workarea = {monitor.x + 50, monitor.y + 50, monitor.width - 100, monitor.height - 150}; @@ -53,12 +95,16 @@ namespace Gala if (n_windows == 0) return; + grab_key_focus (); + var rows = (int)Math.ceilf (Math.sqrtf (n_windows)); var cols = (int)Math.ceilf (n_windows / (float)rows); plugin.begin_modal (); Utils.set_input_area (screen, InputArea.FULLSCREEN); + visible = true; + var i = 0; windows.foreach ((w) => { var actor = w.get_compositor_private () as WindowActor; @@ -80,8 +126,6 @@ namespace Gala float dest_h = actor.height; float dest_x, dest_y, max_width, max_height; - visible = true; - if (n_windows > POSITIONS.length[0]) { max_width = workarea.width / cols - 50; max_height = workarea.height / rows - 50; @@ -107,14 +151,15 @@ namespace Gala dest_x += max_width / 2 - dest_w / 2; //center them dest_y += max_height / 2 - dest_h / 2; + clone.icon.x = dest_x + (clone.width * scale_x) / 2 - clone.icon.width/2; + clone.icon.y = dest_y + clone.height*scale_y - 30; + clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); + if (animate) { - clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, - scale_x:scale_x, scale_y:scale_y, x:dest_x, y:dest_y).completed.connect (() => { - - clone.icon.x = clone.x + (clone.width * scale_x) / 2 - clone.icon.width/2; - clone.icon.y = clone.y + clone.height*scale_y - 30; - clone.icon.raise_top (); - clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 150, scale_x:1.0f, scale_y:1.0f); + clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:scale_x, scale_y:scale_y, x:dest_x, y:dest_y); + clone.icon.opacity = 0; + clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255).completed.connect (() => { + ready = true; }); } else { clone.scale_x = scale_x; @@ -122,9 +167,6 @@ namespace Gala clone.x = dest_x; clone.y = dest_y; - clone.icon.x = clone.x + (clone.width * scale_x) / 2 - clone.icon.width/2; - clone.icon.y = clone.y + clone.height*scale_y - 30; - clone.icon.raise_top (); clone.icon.scale_x = 1.0f; clone.icon.scale_y = 1.0f; } @@ -144,6 +186,11 @@ namespace Gala void close (bool animate = true) { + if (!visible || !ready) + return; + + ready = false; + plugin.end_modal (); plugin.update_input_area (); @@ -156,9 +203,12 @@ namespace Gala if (animate) { Timeout.add (250, () => { visible = false; + ready = true; + return false; }); } else { + ready = true; visible = false; } } diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index a893f57b..42926a91 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -61,12 +61,16 @@ namespace Gala { unowned Rectangle rect = window.get_outer_rect (); - //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized windows + //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized ones float delta = (window.maximized_horizontally || window.maximized_vertically)?0:10; float dest_x = rect.x - delta; float dest_y = rect.y - delta; + //stop all running animations + detach_animation (); + icon.detach_animation (); + icon.animate (Clutter.AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f) .completed.connect ( () => { icon.destroy (); diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index c60fc78b..ac399f76 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -294,12 +294,12 @@ namespace Gala var screen = plugin.get_screen (); - Utils.set_input_area (screen, InputArea.FULLSCREEN); - plugin.begin_modal (); - visible = true; grab_key_focus (); + Utils.set_input_area (screen, InputArea.FULLSCREEN); + plugin.begin_modal (); + if (wait) { timeout = Timeout.add (1000, () => { show_elements (); From 919bd3b752f2b805bcff17385ec957a607843b8f Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 4 Aug 2012 13:00:15 +0200 Subject: [PATCH 04/46] Fix deprecation warnings --- src/Widgets/ExposedWindow.vala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index 42926a91..79e782cc 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -19,7 +19,7 @@ using Meta; namespace Gala { - public class ExposedWindow : Clutter.Group + public class ExposedWindow : Clutter.Actor { public weak Window window; Clutter.Clone clone; @@ -51,7 +51,7 @@ namespace Gala public override bool button_press_event (Clutter.ButtonEvent event) { - raise_top (); + get_parent ().set_child_above_sibling (this, null); selected (window); return true; From 04302e415fc3b697f5ef6e7b868a54af81caa131 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 4 Aug 2012 23:11:23 +0200 Subject: [PATCH 05/46] Add a nudge over animation when trying to switch to a non existent workspace --- src/Widgets/WorkspaceView.vala | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index c60fc78b..d9af4d02 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -199,13 +199,21 @@ namespace Gala void switch_to_next_workspace (MotionDirection direction) { - var screen = plugin.get_screen (); var display = screen.get_display (); - var neighbor = screen.get_active_workspace ().get_neighbor (direction); - if (neighbor == null) + //mutter always returns a valid workspace, so we have to figure out ourselves if it was the last/first one + //and then do our animation + var idx = screen.get_active_workspace ().index () + (direction == MotionDirection.LEFT ? -1 : 1); + if (idx < 0 || idx > screen.n_workspaces - 1) { + var dest = direction == MotionDirection.LEFT ? 32.0f : -32.0f; + Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 100, x:dest); + Clutter.Threads.Timeout.add (210, () => { + Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 150, x:0.0f); + return false; + }); return; + } neighbor.activate (display.get_current_time ()); } From 2890c555b700a61fd6c5f5a7c3892f24188090bb Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 4 Aug 2012 23:23:04 +0200 Subject: [PATCH 06/46] Simplify the check for not having moved workspace --- src/Widgets/WorkspaceView.vala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index d9af4d02..1e575d41 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -202,20 +202,17 @@ namespace Gala var display = screen.get_display (); var neighbor = screen.get_active_workspace ().get_neighbor (direction); - //mutter always returns a valid workspace, so we have to figure out ourselves if it was the last/first one - //and then do our animation - var idx = screen.get_active_workspace ().index () + (direction == MotionDirection.LEFT ? -1 : 1); - if (idx < 0 || idx > screen.n_workspaces - 1) { + neighbor.activate (display.get_current_time ()); + + //if we didnt switch, show a nudge-over animation + if (screen.get_active_workspace () == neighbor) { var dest = direction == MotionDirection.LEFT ? 32.0f : -32.0f; Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 100, x:dest); Clutter.Threads.Timeout.add (210, () => { Compositor.get_window_group_for_screen (screen).animate (Clutter.AnimationMode.LINEAR, 150, x:0.0f); return false; }); - return; } - - neighbor.activate (display.get_current_time ()); } public override bool leave_event (Clutter.CrossingEvent event) { From 26eaa3dd345388bf5ebd44d76c951ecf78eff465 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Tue, 7 Aug 2012 10:21:07 +0200 Subject: [PATCH 07/46] Some cleanups --- src/Expo.vala | 35 +++++++++++++++++++++------------- src/Widgets/ExposedWindow.vala | 29 ++++++++++++---------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 066b6f72..2df16b00 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -22,12 +22,13 @@ namespace Gala { public class Expo : Actor { - Plugin plugin; Screen screen; bool ready; + static const int PADDING = 50; + public Expo (Plugin _plugin) { plugin = _plugin; @@ -89,6 +90,7 @@ namespace Gala used_windows.append (w); }); + //sort our windows var windows = screen.get_display ().sort_windows_by_stacking (used_windows); var n_windows = used_windows.length (); @@ -97,14 +99,14 @@ namespace Gala grab_key_focus (); - var rows = (int)Math.ceilf (Math.sqrtf (n_windows)); - var cols = (int)Math.ceilf (n_windows / (float)rows); - plugin.begin_modal (); Utils.set_input_area (screen, InputArea.FULLSCREEN); visible = true; + var rows = (int)Math.ceilf (Math.sqrtf (n_windows)); + var cols = (int)Math.ceilf (n_windows / (float)rows); + var i = 0; windows.foreach ((w) => { var actor = w.get_compositor_private () as WindowActor; @@ -127,32 +129,37 @@ namespace Gala float dest_x, dest_y, max_width, max_height; if (n_windows > POSITIONS.length[0]) { - max_width = workarea.width / cols - 50; - max_height = workarea.height / rows - 50; + max_width = workarea.width / cols - PADDING; + max_height = workarea.height / rows - PADDING; - dest_x = workarea.x + workarea.width * ((i % rows) / (float)rows); - dest_y = workarea.y + workarea.height * Math.floorf ((i / (float)rows)) / (float)cols; + dest_x = workarea.x + workarea.width * (i % rows / (float)rows); + dest_y = workarea.y + workarea.height * Math.floorf (i / (float)rows) / cols; } else { - max_width = workarea.width * POSITIONS[n_windows-1,i,2] - 50; - max_height = workarea.height * POSITIONS[n_windows-1,i,3] - 50; + max_width = workarea.width * POSITIONS[n_windows-1,i,2] - PADDING; + max_height = workarea.height * POSITIONS[n_windows-1,i,3] - PADDING; dest_x = workarea.x + workarea.width * POSITIONS[n_windows-1,i,0]; dest_y = workarea.y + workarea.height * POSITIONS[n_windows-1,i,1]; } + //if the window doesnt fit at full size, scale it down if (dest_w > max_width || dest_h > max_height) { var aspect = (max_width / dest_w < max_height / dest_h) ? max_width / dest_w : max_height / dest_h; + dest_w = dest_w * aspect; dest_h = dest_h * aspect; scale_x = (dest_w) / actor.width; scale_y = (dest_h) / actor.height; } - dest_x += max_width / 2 - dest_w / 2; //center them + //center the windows in their rects + dest_x += max_width / 2 - dest_w / 2; dest_y += max_height / 2 - dest_h / 2; - clone.icon.x = dest_x + (clone.width * scale_x) / 2 - clone.icon.width/2; - clone.icon.y = dest_y + clone.height*scale_y - 30; + // place the windows icon, it is outside the window's actor since the whole actor is scaled and if + // we'd 'counter'-scale the icon it will look blurry + clone.icon.x = dest_x + (clone.width * scale_x) / 2 - clone.icon.width / 2; + clone.icon.y = dest_y + clone.height * scale_y - 30; clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); if (animate) { @@ -169,6 +176,8 @@ namespace Gala clone.icon.scale_x = 1.0f; clone.icon.scale_y = 1.0f; + + ready = true; } add_child (clone); diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index 79e782cc..c3d01a8d 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -31,15 +31,16 @@ namespace Gala { window = _window; - var actor = _window.get_compositor_private () as WindowActor; - clone = new Clutter.Clone (actor.get_texture ()); - reactive = true; + var actor = window.get_compositor_private () as WindowActor; + clone = new Clutter.Clone (actor.get_texture ()); + icon = new GtkClutter.Texture (); icon.scale_x = 0.0f; icon.scale_y = 0.0f; icon.scale_gravity = Clutter.Gravity.CENTER; + try { icon.set_from_pixbuf (Utils.get_icon_for_window (window, 64)); } catch (Error e) { warning (e.message); } @@ -62,7 +63,7 @@ namespace Gala unowned Rectangle rect = window.get_outer_rect (); //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized ones - float delta = (window.maximized_horizontally || window.maximized_vertically)?0:10; + float delta = window.maximized_horizontally || window.maximized_vertically ? 0 : 10; float dest_x = rect.x - delta; float dest_y = rect.y - delta; @@ -71,26 +72,20 @@ namespace Gala detach_animation (); icon.detach_animation (); - icon.animate (Clutter.AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f) - .completed.connect ( () => { - icon.destroy (); - }); - if (do_animate) { - animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, - scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { - + icon.animate (Clutter.AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f).completed.connect ( () => { + icon.destroy (); + }); + + animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { (window.get_compositor_private () as Clutter.Actor).show (); destroy (); }); } else { - scale_x = 1.0f; - scale_y = 1.0f; - x = dest_x; - y = dest_y; - (window.get_compositor_private () as Clutter.Actor).show (); + destroy (); + icon.destroy (); } } } From 1ca06f2014dbe63568c4d89a39c0e978bae9eeb2 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Tue, 7 Aug 2012 11:02:40 +0200 Subject: [PATCH 08/46] Add delay when holding down arrow keys while switching workspaces --- src/Widgets/WorkspaceView.vala | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index 1e575d41..8f71db5d 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -222,20 +222,35 @@ namespace Gala return false; } + uint last_time = -1; + bool released = false; public override bool key_press_event (Clutter.KeyEvent event) { + var display = screen.get_display (); + + if (!released && display.get_current_time_roundtrip () < (last_time + AnimationSettings.get_default ().workspace_switch_duration)) + return false; + switch (event.keyval) { case Clutter.Key.Left: if ((event.modifier_state & Clutter.ModifierType.SHIFT_MASK) == 1) - plugin.move_window (screen.get_display ().get_focus_window (), MotionDirection.LEFT); + plugin.move_window (display.get_focus_window (), MotionDirection.LEFT); else switch_to_next_workspace (MotionDirection.LEFT); + + released = false; + last_time = display.get_current_time_roundtrip (); + return false; case Clutter.Key.Right: if ((event.modifier_state & Clutter.ModifierType.SHIFT_MASK) == 1) - plugin.move_window (screen.get_display ().get_focus_window (), MotionDirection.RIGHT); + plugin.move_window (display.get_focus_window (), MotionDirection.RIGHT); else switch_to_next_workspace (MotionDirection.RIGHT); + + released = false; + last_time = display.get_current_time_roundtrip (); + return false; default: break; @@ -246,6 +261,8 @@ namespace Gala public override bool key_release_event (Clutter.KeyEvent event) { + released = true; + if (event.keyval == Clutter.Key.Alt_L || event.keyval == Clutter.Key.Super_L || event.keyval == Clutter.Key.Control_L || @@ -352,8 +369,11 @@ namespace Gala return false; }); //catch hot corner hiding problem and indicator placement + var wins = Compositor.get_window_group_for_screen (screen); + wins.detach_animation (); + animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : (area.height + area.y) - height); - Compositor.get_window_group_for_screen (plugin.get_screen ()).animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : -height + 1); + wins.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : -height + 1); } public new void hide () @@ -376,7 +396,9 @@ namespace Gala click_catcher.visible = false; - Compositor.get_window_group_for_screen (plugin.get_screen ()).animate (Clutter.AnimationMode.EASE_OUT_EXPO, 500, y : 0.0f); + var wins = Compositor.get_window_group_for_screen (screen); + wins.detach_animation (); + wins.animate (Clutter.AnimationMode.EASE_OUT_EXPO, 500, y : 0.0f); } public void handle_switch_to_workspace (Meta.Display display, Meta.Screen screen, Meta.Window? window, From 2d956305ae2d8f0e2b48a65d9edef0f0b1a9aaaf Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 9 Aug 2012 00:21:57 +0200 Subject: [PATCH 09/46] Fix a crash when opening and closing the same window quite quickly --- src/Plugin.vala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Plugin.vala b/src/Plugin.vala index d431c940..448ceebc 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -381,6 +381,7 @@ namespace Gala var display = screen.get_display (); var window = actor.get_meta_window (); + actor.detach_animation (); actor.show (); switch (window.window_type) { @@ -454,6 +455,7 @@ namespace Gala var display = screen.get_display (); var window = actor.get_meta_window (); + actor.detach_animation (); destroying.add (actor); switch (window.window_type) { From 4307c157c09675dfd5d94e4fbbe8f61b20f3d261 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 9 Aug 2012 01:04:29 +0200 Subject: [PATCH 10/46] Remove some calls to deprecated methods --- src/Widgets/WorkspaceThumb.vala | 16 ++++++++++++---- src/Widgets/WorkspaceView.vala | 27 ++++++++++++++++----------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Widgets/WorkspaceThumb.vala b/src/Widgets/WorkspaceThumb.vala index 260c3fb4..d671678a 100644 --- a/src/Widgets/WorkspaceThumb.vala +++ b/src/Widgets/WorkspaceThumb.vala @@ -46,7 +46,7 @@ namespace Gala internal Clone wallpaper; Clutter.Actor windows; internal Clutter.Actor icons; - CairoTexture indicator; + Actor indicator; GtkClutter.Texture close_button; uint hover_timer = 0; @@ -75,10 +75,14 @@ namespace Gala reactive = true; - indicator = new Clutter.CairoTexture ((uint)width + 2 * INDICATOR_BORDER, (uint)THUMBNAIL_HEIGHT + 2 * INDICATOR_BORDER); - indicator.draw.connect (draw_indicator); - indicator.auto_resize = true; + indicator = new Actor (); + indicator.width = width + 2 * INDICATOR_BORDER; + indicator.height = THUMBNAIL_HEIGHT + 2 * INDICATOR_BORDER; indicator.opacity = 0; + indicator.content = new Canvas (); + (indicator.content as Canvas).draw.connect (draw_indicator); + (indicator.content as Canvas).set_size ((int)indicator.width, (int)indicator.height); + handle_workspace_switched (-1, screen.get_active_workspace_index (), MotionDirection.LEFT); // FIXME find a nice way to draw a border around it, maybe combinable with the indicator using a ShaderEffect @@ -208,6 +212,10 @@ namespace Gala bool draw_indicator (Cairo.Context cr) { + cr.set_operator (Cairo.Operator.CLEAR); + cr.paint (); + cr.set_operator (Cairo.Operator.OVER); + selector_style.render_activity (cr, 0, 0, indicator.width, indicator.height); return false; diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index 8f71db5d..b08d69e9 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -27,8 +27,7 @@ namespace Gala Screen screen; Clutter.Actor thumbnails; - Clutter.CairoTexture background; - Clutter.CairoTexture scroll; + Clutter.Actor scroll; Clutter.Actor click_catcher; //invisible plane that catches clicks outside the view bool animating; // delay closing the popup @@ -58,16 +57,13 @@ namespace Gala (thumbnails.layout_manager as Clutter.BoxLayout).spacing = 12; (thumbnails.layout_manager as Clutter.BoxLayout).homogeneous = true; - background = new Clutter.CairoTexture (500, (uint)height); - background.auto_resize = true; - background.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.WIDTH, 0)); - background.add_constraint (new Clutter.BindConstraint (this, Clutter.BindCoordinate.HEIGHT, 0)); - background.draw.connect (draw_background); + content = new Clutter.Canvas (); + (content as Clutter.Canvas).draw.connect (draw_background); - scroll = new Clutter.CairoTexture (100, 12); + scroll = new Clutter.Actor (); scroll.height = 12; - scroll.auto_resize = true; - scroll.draw.connect (draw_scroll); + scroll.content = new Clutter.Canvas (); + (scroll.content as Clutter.Canvas).draw.connect (draw_scroll); click_catcher = new Clutter.Actor (); click_catcher.reactive = true; @@ -77,7 +73,6 @@ namespace Gala }); Compositor.get_stage_for_screen (screen).add_child (click_catcher); - add_child (background); add_child (thumbnails); add_child (scroll); @@ -125,6 +120,10 @@ namespace Gala bool draw_background (Cairo.Context cr) { + cr.set_operator (Cairo.Operator.CLEAR); + cr.paint (); + cr.set_operator (Cairo.Operator.OVER); + background_style.render_background (cr, 0, 0, width, height); background_style.render_frame (cr, 0, 0, width, height); @@ -133,6 +132,10 @@ namespace Gala bool draw_scroll (Cairo.Context cr) { + cr.set_operator (Cairo.Operator.CLEAR); + cr.paint (); + cr.set_operator (Cairo.Operator.OVER); + Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, 4, 4, scroll.width-32, 4, 2); cr.set_source_rgba (1, 1, 1, 0.8); cr.fill (); @@ -192,6 +195,7 @@ namespace Gala if (thumbnails.x + thumbnails.width < width) thumbnails.x = width - thumbnails.width; scroll.width = width / thumbnails.width * width; + (scroll.content as Clutter.Canvas).set_size ((int)scroll.width, 12); } else { thumbnails.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, x : width / 2 - thumbnails.width / 2); } @@ -338,6 +342,7 @@ namespace Gala y = area.height + area.y; x = area.x; width = area.width; + (content as Clutter.Canvas).set_size ((int)width, (int)height); thumbnails.get_children ().foreach ((thumb) => { thumb.show (); From 9d4286eba9d1c40cc1d2876a340d5687568a6b42 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Thu, 9 Aug 2012 11:27:17 +0200 Subject: [PATCH 11/46] Some clean ups and make coords calculation more stable --- src/Expo.vala | 63 ++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 2df16b00..7dd7fbfb 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -34,7 +34,7 @@ namespace Gala plugin = _plugin; screen = plugin.get_screen (); - screen.workspace_switched.connect (() => close (false) ); + screen.workspace_switched.connect (() => close (false)); visible = false; ready = true; @@ -67,13 +67,13 @@ namespace Gala {{0.0f, 0.0f, 0.3f, 0.5f}, {0.3f, 0.0f, 0.3f, 0.5f}, {0.6f, 0.0f, 0.3f, 0.5f}, {0.0f, 0.5f, 0.3f, 0.5f}, {0.3f, 0.5f, 0.3f, 0.5f}, {0.6f, 0.5f, 0.3f, 0.5f}} }; - public void open (bool animate=true) + public void open (bool animate = true) { if (!ready) return; if (visible) { - close (); + close (true); return; } @@ -90,13 +90,13 @@ namespace Gala used_windows.append (w); }); - //sort our windows - var windows = screen.get_display ().sort_windows_by_stacking (used_windows); - var n_windows = used_windows.length (); if (n_windows == 0) return; + // sort windows by stacking order + var windows = screen.get_display ().sort_windows_by_stacking (used_windows); + grab_key_focus (); plugin.begin_modal (); @@ -104,8 +104,8 @@ namespace Gala visible = true; - var rows = (int)Math.ceilf (Math.sqrtf (n_windows)); - var cols = (int)Math.ceilf (n_windows / (float)rows); + var rows = Math.ceilf (Math.sqrtf (n_windows)); + var cols = Math.ceilf (n_windows / rows); var i = 0; windows.foreach ((w) => { @@ -121,45 +121,46 @@ namespace Gala clone.x = actor.x; clone.y = actor.y; - //calculate new rect + // calculate new size to fit our grid float scale_x = 1.0f; float scale_y = 1.0f; float dest_w = actor.width; float dest_h = actor.height; float dest_x, dest_y, max_width, max_height; - if (n_windows > POSITIONS.length[0]) { - max_width = workarea.width / cols - PADDING; - max_height = workarea.height / rows - PADDING; + // use pre-calculated positions for a limited window-count + if (n_windows <= POSITIONS.length[0]) { + max_width = Math.floorf (workarea.width * POSITIONS[n_windows-1,i,2] - PADDING); + max_height = Math.floorf (workarea.height * POSITIONS[n_windows-1,i,3] - PADDING); - dest_x = workarea.x + workarea.width * (i % rows / (float)rows); - dest_y = workarea.y + workarea.height * Math.floorf (i / (float)rows) / cols; + dest_x = workarea.x + Math.floorf (workarea.width * POSITIONS[n_windows-1,i,0]); + dest_y = workarea.y + Math.floorf (workarea.height * POSITIONS[n_windows-1,i,1]); } else { - max_width = workarea.width * POSITIONS[n_windows-1,i,2] - PADDING; - max_height = workarea.height * POSITIONS[n_windows-1,i,3] - PADDING; + max_width = Math.floorf (workarea.width / cols - PADDING); + max_height = Math.floorf (workarea.height / rows - PADDING); - dest_x = workarea.x + workarea.width * POSITIONS[n_windows-1,i,0]; - dest_y = workarea.y + workarea.height * POSITIONS[n_windows-1,i,1]; + dest_x = workarea.x + Math.floorf (workarea.width * (i % (int)rows) / rows); + dest_y = workarea.y + Math.floorf (workarea.height * (int)(i / rows) / cols); } - //if the window doesnt fit at full size, scale it down + // if the window doesnt fit at full size, scale it down if (dest_w > max_width || dest_h > max_height) { - var aspect = (max_width / dest_w < max_height / dest_h) ? max_width / dest_w : max_height / dest_h; + var aspect = (max_width / dest_w < max_height / dest_h ? max_width / dest_w : max_height / dest_h); - dest_w = dest_w * aspect; - dest_h = dest_h * aspect; - scale_x = (dest_w) / actor.width; - scale_y = (dest_h) / actor.height; + dest_w = Math.floorf (dest_w * aspect); + dest_h = Math.floorf (dest_h * aspect); + scale_x = dest_w / actor.width; + scale_y = dest_h / actor.height; } - //center the windows in their rects - dest_x += max_width / 2 - dest_w / 2; - dest_y += max_height / 2 - dest_h / 2; + // center the windows in their rects + dest_x += Math.floorf (max_width / 2.0f - dest_w / 2.0f); + dest_y += Math.floorf (max_height / 2.0f - dest_h / 2.0f); // place the windows icon, it is outside the window's actor since the whole actor is scaled and if // we'd 'counter'-scale the icon it will look blurry - clone.icon.x = dest_x + (clone.width * scale_x) / 2 - clone.icon.width / 2; - clone.icon.y = dest_y + clone.height * scale_y - 30; + clone.icon.x = dest_x + Math.floorf (clone.width * scale_x / 2.0f - clone.icon.width / 2.0f); + clone.icon.y = dest_y + Math.floorf (clone.height * scale_y - 30.0f); clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); if (animate) { @@ -182,7 +183,7 @@ namespace Gala add_child (clone); - i ++; + i++; }); } @@ -193,7 +194,7 @@ namespace Gala close (true); } - void close (bool animate = true) + void close (bool animate) { if (!visible || !ready) return; From 5011d779c963501692f2ff852f227c3bc78b7873 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 9 Aug 2012 17:20:04 +0200 Subject: [PATCH 12/46] Fix problem where the window group would stay at x!=0 when having released super to early while switching --- src/Widgets/WorkspaceView.vala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Widgets/WorkspaceView.vala b/src/Widgets/WorkspaceView.vala index b08d69e9..8606b063 100644 --- a/src/Widgets/WorkspaceView.vala +++ b/src/Widgets/WorkspaceView.vala @@ -376,6 +376,7 @@ namespace Gala var wins = Compositor.get_window_group_for_screen (screen); wins.detach_animation (); + wins.x = 0.0f; animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : (area.height + area.y) - height); wins.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 250, y : -height + 1); @@ -403,6 +404,7 @@ namespace Gala var wins = Compositor.get_window_group_for_screen (screen); wins.detach_animation (); + wins.x = 0.0f; wins.animate (Clutter.AnimationMode.EASE_OUT_EXPO, 500, y : 0.0f); } From 3abba68cc1c75a5a7bc66f3bc9e76d15c6c356a8 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 12 Aug 2012 12:08:01 +0200 Subject: [PATCH 13/46] Only minimize NORMAL windows by action --- src/Plugin.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index 448ceebc..340d7782 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -262,7 +262,7 @@ namespace Gala current.maximize (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL); break; case ActionType.MINIMIZE_CURRENT: - if (current != null) + if (current != null && current.window_type == WindowType.NORMAL) current.minimize (); break; case ActionType.OPEN_LAUNCHER: From bdbca6d59a10e7ab663d765b1fd4b948b250a164 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 12 Aug 2012 12:09:49 +0200 Subject: [PATCH 14/46] Only maximize NORMAL windows by action --- src/Plugin.vala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index 340d7782..c6e21804 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -254,8 +254,9 @@ namespace Gala workspace_view.show (); break; case ActionType.MAXIMIZE_CURRENT: - if (current == null) + if (current == null || current.window_type != WindowType.NORMAL) break; + if (current.get_maximized () == (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL)) current.unmaximize (MaximizeFlags.HORIZONTAL | MaximizeFlags.VERTICAL); else From 0e4992beddc2c54268b7d7b40c4271f629505a2b Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 16 Aug 2012 23:48:40 +0200 Subject: [PATCH 15/46] Fix style applying in workspacethumb --- src/Widgets/WorkspaceThumb.vala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Widgets/WorkspaceThumb.vala b/src/Widgets/WorkspaceThumb.vala index d671678a..4953ea01 100644 --- a/src/Widgets/WorkspaceThumb.vala +++ b/src/Widgets/WorkspaceThumb.vala @@ -216,7 +216,8 @@ namespace Gala cr.paint (); cr.set_operator (Cairo.Operator.OVER); - selector_style.render_activity (cr, 0, 0, indicator.width, indicator.height); + selector_style.render_background (cr, 0, 0, indicator.width, indicator.height); + selector_style.render_frame (cr, 0, 0, indicator.width, indicator.height); return false; } From 66cc19c27d656d9eb500a6e469d11220bff9b8e3 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 19 Aug 2012 14:43:48 +0200 Subject: [PATCH 16/46] Adjust expose brach to use GS extension natural window placement extension expo code --- src/Expo.vala | 258 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 171 insertions(+), 87 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 7dd7fbfb..c4e4e29d 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -57,15 +57,167 @@ namespace Gala close (false); } - //vala doesnt support multidimensional array of different sizes, that's why we fill them up with 0s - static float [,,] POSITIONS = { - {{0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, - {{0.0f, 0.0f, 0.5f, 1.0f}, {0.5f, 0.0f, 0.5f, 1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, - {{0.0f, 0.0f, 0.5f, 0.5f}, {0.5f, 0.0f, 0.5f, 0.5f}, {0.0f, 0.5f, 1.0f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, - {{0.0f, 0.0f, 0.5f, 0.5f}, {0.5f, 0.0f, 0.5f, 0.5f}, {0.0f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}, - {{0.0f, 0.0f, 0.3f, 0.5f}, {0.3f, 0.0f, 0.3f, 0.5f}, {0.6f, 0.0f, 0.3f, 0.5f}, {0.0f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 0.0f, 0.0f}}, - {{0.0f, 0.0f, 0.3f, 0.5f}, {0.3f, 0.0f, 0.3f, 0.5f}, {0.6f, 0.0f, 0.3f, 0.5f}, {0.0f, 0.5f, 0.3f, 0.5f}, {0.3f, 0.5f, 0.3f, 0.5f}, {0.6f, 0.5f, 0.3f, 0.5f}} - }; + /** + * Code borrowed from native window placement GS extension + * http://git.gnome.org/browse/gnome-shell-extensions/tree/extensions/native-window-placement/extension.js + **/ + const int GAPS = 5; + const int MAX_TRANSLATIONS = 5000; + const int ACCURACY = 20; + const int BORDER = 10; + const int TOP = 20; + const bool use_more_screen = true; + + int[] rect_center (Meta.Rectangle rect) + { + return {rect.width / 2, rect.height / 2}; + } + Meta.Rectangle rect_adjusted (Meta.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)}; + } + + void calculate_places (List windows) + { + var clones = windows.copy (); + clones.sort ((a, b) => { + return (int)(a as ExposedWindow).window.get_stable_sequence () - (int)(b as ExposedWindow).window.get_stable_sequence (); + }); + + //get a working area + var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); + var ratio = monitor.width / (float)monitor.height; + var x_gap = Math.fmaxf (BORDER, TOP * ratio); + var y_gap = Math.fmaxf (BORDER / ratio, TOP); + Meta.Rectangle area = {(int)Math.floorf (monitor.x + x_gap / 2), + (int)Math.floorf (monitor.y + y_gap / 2), + (int)Math.floorf (monitor.width - x_gap), + (int)Math.floorf (monitor.height - y_gap)}; + + //get a copy + Meta.Rectangle bounds = {area.x, area.y, area.width, area.height}; + + var direction = 0; + var directions = new List (); + var rects = new List (); + foreach (var clone in clones) { + var rect = (clone as ExposedWindow).window.get_outer_rect (); + rects.append (rect); + bounds = bounds.union (rect); + + directions.append (direction); + direction ++; + if (direction == 4) + direction = 0; + } + + int loop_counter = 0; + bool overlap = false; + do { + overlap = false; + for (var i=0;i area.height / (float)area.width) + diff[0] *= 2; + else + diff[1] *= 2; + + var length = Math.sqrtf (diff[0] * diff[0] + diff[1] * diff[1]); + diff[0] = (int)Math.floorf (diff[0] * ACCURACY / length); + diff[1] = (int)Math.floorf (diff[1] * ACCURACY / length); + + rects.nth_data (i).x += -diff[0]; + rects.nth_data (i).y += -diff[1]; + rects.nth_data (j).x += diff[0]; + rects.nth_data (j).y += diff[1]; + + if (use_more_screen) { + var x_section = Math.round ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); + var y_section = Math.round ((rects.nth_data (i).y - bounds.y) / (bounds.height / 3.0f)); + + i_center = rect_center (rects.nth_data (i)); + diff[0] = 0; + diff[1] = 0; + if (x_section != 1 || y_section != 1) { + if (x_section == 1) + x_section = directions.nth_data (i) / 2 == 1 ? 2 : 0; + if (y_section == 1) + y_section = directions.nth_data (i) % 2 == 1 ? 2 : 0; + } + if (x_section == 0 && y_section == 0) { + diff[0] = bounds.x - i_center[0]; + diff[1] = bounds.y - i_center[1]; + } + if (x_section == 2 && y_section == 0) { + diff[0] = bounds.x + bounds.width - i_center[0]; + diff[1] = bounds.y - i_center[1]; + } + if (x_section == 2 && y_section == 2) { + diff[0] = bounds.x + bounds.width - i_center[0]; + diff[1] = bounds.y + bounds.height - i_center[1]; + } + if (x_section == 0 && y_section == 2) { + diff[0] = bounds.x - i_center[0]; + diff[1] = bounds.y + bounds.height - i_center[1]; + } + if (diff[0] != 0 || diff[1] != 0) { + length = Math.sqrtf (diff[0] * diff[0] + diff[1] * diff[1]); + diff[0] *= (int)Math.floorf (ACCURACY / length / 2.0f); + diff[1] *= (int)Math.floorf (ACCURACY / length / 2.0f); + rects.nth_data (i).x += diff[0]; + rects.nth_data (i).y += diff[1]; + } + } + + bounds = bounds.union (rects.nth_data (i)); + bounds = bounds.union (rects.nth_data (j)); + } + } + } + } while (overlap && loop_counter < MAX_TRANSLATIONS); + + var scale = Math.fminf (Math.fminf (area.width / (float)bounds.width, area.height / (float)bounds.height), 1.0f); + bounds.x = (int)Math.floorf (bounds.x - (area.width - bounds.width * scale) / 2.0f); + bounds.y = (int)Math.floorf (bounds.y - (area.height - bounds.height * scale) / 2.0f); + bounds.width = (int)Math.floorf (area.width / scale); + bounds.height = (int)Math.floorf (area.height / scale); + + foreach (var rect in rects) { + rect.x += -bounds.x; + rect.y += -bounds.y; + } + + for (var i=0;i ready = true ); + clone.icon.opacity = 0; + clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); + } + } public void open (bool animate = true) { @@ -79,9 +231,6 @@ namespace Gala ready = false; - var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); - Meta.Rectangle workarea = {monitor.x + 50, monitor.y + 50, monitor.width - 100, monitor.height - 150}; - var used_windows = new SList (); screen.get_active_workspace ().list_windows ().foreach ((w) => { @@ -104,87 +253,22 @@ namespace Gala visible = true; - var rows = Math.ceilf (Math.sqrtf (n_windows)); - var cols = Math.ceilf (n_windows / rows); - - var i = 0; - windows.foreach ((w) => { - var actor = w.get_compositor_private () as WindowActor; + foreach (var window in windows) { + var actor = window.get_compositor_private () as WindowActor; if (actor == null) return; actor.hide (); - var clone = new ExposedWindow (w); - - clone.selected.connect (selected); - + var clone = new ExposedWindow (window); clone.x = actor.x; clone.y = actor.y; - // calculate new size to fit our grid - float scale_x = 1.0f; - float scale_y = 1.0f; - float dest_w = actor.width; - float dest_h = actor.height; - float dest_x, dest_y, max_width, max_height; - - // use pre-calculated positions for a limited window-count - if (n_windows <= POSITIONS.length[0]) { - max_width = Math.floorf (workarea.width * POSITIONS[n_windows-1,i,2] - PADDING); - max_height = Math.floorf (workarea.height * POSITIONS[n_windows-1,i,3] - PADDING); - - dest_x = workarea.x + Math.floorf (workarea.width * POSITIONS[n_windows-1,i,0]); - dest_y = workarea.y + Math.floorf (workarea.height * POSITIONS[n_windows-1,i,1]); - } else { - max_width = Math.floorf (workarea.width / cols - PADDING); - max_height = Math.floorf (workarea.height / rows - PADDING); - - dest_x = workarea.x + Math.floorf (workarea.width * (i % (int)rows) / rows); - dest_y = workarea.y + Math.floorf (workarea.height * (int)(i / rows) / cols); - } - - // if the window doesnt fit at full size, scale it down - if (dest_w > max_width || dest_h > max_height) { - var aspect = (max_width / dest_w < max_height / dest_h ? max_width / dest_w : max_height / dest_h); - - dest_w = Math.floorf (dest_w * aspect); - dest_h = Math.floorf (dest_h * aspect); - scale_x = dest_w / actor.width; - scale_y = dest_h / actor.height; - } - - // center the windows in their rects - dest_x += Math.floorf (max_width / 2.0f - dest_w / 2.0f); - dest_y += Math.floorf (max_height / 2.0f - dest_h / 2.0f); - - // place the windows icon, it is outside the window's actor since the whole actor is scaled and if - // we'd 'counter'-scale the icon it will look blurry - clone.icon.x = dest_x + Math.floorf (clone.width * scale_x / 2.0f - clone.icon.width / 2.0f); - clone.icon.y = dest_y + Math.floorf (clone.height * scale_y - 30.0f); - clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); - - if (animate) { - clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:scale_x, scale_y:scale_y, x:dest_x, y:dest_y); - clone.icon.opacity = 0; - clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255).completed.connect (() => { - ready = true; - }); - } else { - clone.scale_x = scale_x; - clone.scale_y = scale_y; - clone.x = dest_x; - clone.y = dest_y; - - clone.icon.scale_x = 1.0f; - clone.icon.scale_y = 1.0f; - - ready = true; - } + clone.selected.connect (selected); add_child (clone); - - i++; - }); + } + + calculate_places (get_children ()); } void selected (Window window) @@ -204,11 +288,11 @@ namespace Gala plugin.end_modal (); plugin.update_input_area (); - get_children ().foreach ( (c) => { - var exposed = c as ExposedWindow; + foreach (var child in get_children ()) { + var exposed = child as ExposedWindow; exposed.close (animate); exposed.selected.disconnect (selected); - }); + } if (animate) { Timeout.add (250, () => { From 449f9d24136436456f97de565a9d9d697d1603a4 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sun, 19 Aug 2012 15:56:07 +0200 Subject: [PATCH 17/46] vapi: rebuild bindings --- src/Plugin.vala | 2 +- vapi/gdesktopenums-3.0.vapi | 30 ++++++++++---------- vapi/libmutter.vapi | 56 ++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index c6e21804..f9a4212e 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -300,7 +300,7 @@ namespace Gala get_screen ().get_size (out width, out height); Rectangle icon = {}; - if (false && actor.get_meta_window ().get_icon_geometry (icon)) { + if (false && actor.get_meta_window ().get_icon_geometry (out icon)) { float scale_x = (float)icon.width / actor.width; float scale_y = (float)icon.height / actor.height; diff --git a/vapi/gdesktopenums-3.0.vapi b/vapi/gdesktopenums-3.0.vapi index 3f9026c6..ac79d309 100644 --- a/vapi/gdesktopenums-3.0.vapi +++ b/vapi/gdesktopenums-3.0.vapi @@ -2,13 +2,13 @@ [CCode (cprefix = "GDesktop", gir_namespace = "GDesktopEnums", gir_version = "3.0", lower_case_cprefix = "g_desktop_")] namespace GDesktop { - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_BACKGROUND_SHADING_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_BACKGROUND_SHADING_", has_type_id = false)] public enum BackgroundShading { SOLID, VERTICAL, HORIZONTAL } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_BACKGROUND_STYLE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_BACKGROUND_STYLE_", has_type_id = false)] public enum BackgroundStyle { NONE, WALLPAPER, @@ -18,30 +18,30 @@ namespace GDesktop { ZOOM, SPANNED } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_CLOCK_FORMAT_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_CLOCK_FORMAT_", has_type_id = false)] public enum ClockFormat { @24H, @12H } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_FOCUS_MODE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_FOCUS_MODE_", has_type_id = false)] public enum FocusMode { CLICK, SLOPPY, MOUSE } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_FOCUS_NEW_WINDOWS_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_FOCUS_NEW_WINDOWS_", has_type_id = false)] public enum FocusNewWindows { SMART, STRICT } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MAGNIFIER_MOUSE_TRACKING_MODE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MAGNIFIER_MOUSE_TRACKING_MODE_", has_type_id = false)] public enum MagnifierMouseTrackingMode { NONE, CENTERED, PROPORTIONAL, PUSH } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MAGNIFIER_SCREEN_POSITION_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MAGNIFIER_SCREEN_POSITION_", has_type_id = false)] public enum MagnifierScreenPosition { NONE, FULL_SCREEN, @@ -50,31 +50,31 @@ namespace GDesktop { LEFT_HALF, RIGHT_HALF } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MOUSE_DWELL_DIRECTION_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MOUSE_DWELL_DIRECTION_", has_type_id = false)] public enum MouseDwellDirection { LEFT, RIGHT, UP, DOWN } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MOUSE_DWELL_MODE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_MOUSE_DWELL_MODE_", has_type_id = false)] public enum MouseDwellMode { WINDOW, GESTURE } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_PROXY_MODE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_PROXY_MODE_", has_type_id = false)] public enum ProxyMode { NONE, MANUAL, AUTO } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_SCREENSAVER_MODE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_SCREENSAVER_MODE_", has_type_id = false)] public enum ScreensaverMode { BLANK_ONLY, RANDOM, SINGLE } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TITLEBAR_ACTION_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TITLEBAR_ACTION_", has_type_id = false)] public enum TitlebarAction { TOGGLE_SHADE, TOGGLE_MAXIMIZE, @@ -85,19 +85,19 @@ namespace GDesktop { LOWER, MENU } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TOOLBAR_ICON_SIZE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TOOLBAR_ICON_SIZE_", has_type_id = false)] public enum ToolbarIconSize { SMALL, LARGE } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TOOLBAR_STYLE_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_TOOLBAR_STYLE_", has_type_id = false)] public enum ToolbarStyle { BOTH, BOTH_HORIZ, ICONS, TEXT } - [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_VISUAL_BELL_")] + [CCode (cheader_filename = "gsettings-desktop-schemas/gdesktop-enums.h", cprefix = "G_DESKTOP_VISUAL_BELL_", has_type_id = false)] public enum VisualBellType { FULLSCREEN_FLASH, FRAME_FLASH diff --git a/vapi/libmutter.vapi b/vapi/libmutter.vapi index dd677470..c76330c5 100644 --- a/vapi/libmutter.vapi +++ b/vapi/libmutter.vapi @@ -445,7 +445,7 @@ namespace Meta { public unowned string get_gtk_menubar_object_path (); public unowned string get_gtk_unique_bus_name (); public unowned string get_gtk_window_object_path (); - public bool get_icon_geometry (Meta.Rectangle rect); + public bool get_icon_geometry (out Meta.Rectangle rect); public Meta.Rectangle get_input_rect (); public Meta.StackLayer get_layer (); public Meta.MaximizeFlags get_maximized (); @@ -677,11 +677,11 @@ namespace Meta { public Meta.Rectangle rect; public Meta.Side side; } - [CCode (cheader_filename = "meta/display.h", cprefix = "META_ATOM_")] + [CCode (cheader_filename = "meta/display.h", cprefix = "META_ATOM_", type_id = "meta_atom_get_type ()")] public enum Atom { FIRST } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_BUTTON_FUNCTION_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_BUTTON_FUNCTION_", type_id = "meta_button_function_get_type ()")] public enum ButtonFunction { MENU, MINIMIZE, @@ -695,7 +695,7 @@ namespace Meta { UNSTICK, LAST } - [CCode (cheader_filename = "meta/compositor.h", cprefix = "META_COMP_EFFECT_")] + [CCode (cheader_filename = "meta/compositor.h", cprefix = "META_COMP_EFFECT_", type_id = "meta_comp_effect_get_type ()")] public enum CompEffect { CREATE, UNMINIMIZE, @@ -703,7 +703,7 @@ namespace Meta { MINIMIZE, NONE } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_CURSOR_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_CURSOR_", type_id = "meta_cursor_get_type ()")] public enum Cursor { DEFAULT, NORTH_RESIZE, @@ -717,7 +717,7 @@ namespace Meta { MOVE_OR_RESIZE_WINDOW, BUSY } - [CCode (cheader_filename = "meta/util.h", cprefix = "META_DEBUG_")] + [CCode (cheader_filename = "meta/util.h", cprefix = "META_DEBUG_", type_id = "meta_debug_topic_get_type ()")] [Flags] public enum DebugTopic { VERBOSE, @@ -744,7 +744,7 @@ namespace Meta { COMPOSITOR, EDGE_RESISTANCE } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_DIRECTION_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_DIRECTION_", type_id = "meta_direction_get_type ()")] [Flags] public enum Direction { LEFT, @@ -756,18 +756,18 @@ namespace Meta { HORIZONTAL, VERTICAL } - [CCode (cheader_filename = "meta/boxes.h", cprefix = "META_EDGE_")] + [CCode (cheader_filename = "meta/boxes.h", cprefix = "META_EDGE_", type_id = "meta_edge_type_get_type ()")] public enum EdgeType { WINDOW, MONITOR, SCREEN } - [CCode (cheader_filename = "meta/main.h", cprefix = "META_EXIT_")] + [CCode (cheader_filename = "meta/main.h", cprefix = "META_EXIT_", type_id = "meta_exit_code_get_type ()")] public enum ExitCode { SUCCESS, ERROR } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_FRAME_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_FRAME_", type_id = "meta_frame_flags_get_type ()")] [Flags] public enum FrameFlags { ALLOWS_DELETE, @@ -788,7 +788,7 @@ namespace Meta { TILED_LEFT, TILED_RIGHT } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_FRAME_TYPE_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_FRAME_TYPE_", type_id = "meta_frame_type_get_type ()")] public enum FrameType { NORMAL, DIALOG, @@ -801,7 +801,7 @@ namespace Meta { [CCode (cheader_filename = "meta/main.h")] public static unowned string to_string (Meta.FrameType type); } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_GRAB_OP_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_GRAB_OP_", type_id = "meta_grab_op_get_type ()")] public enum GrabOp { NONE, MOVING, @@ -843,14 +843,14 @@ namespace Meta { CLICKING_UNSTICK, COMPOSITOR } - [CCode (cheader_filename = "meta/gradient.h", cprefix = "META_GRADIENT_")] + [CCode (cheader_filename = "meta/gradient.h", cprefix = "META_GRADIENT_", type_id = "meta_gradient_type_get_type ()")] public enum GradientType { VERTICAL, HORIZONTAL, DIAGONAL, LAST } - [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_KEYBINDING_ACTION_")] + [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_KEYBINDING_ACTION_", type_id = "meta_key_binding_action_get_type ()")] public enum KeyBindingAction { NONE, WORKSPACE_1, @@ -934,7 +934,7 @@ namespace Meta { MOVE_TO_CENTER, LAST } - [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_KEY_BINDING_")] + [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_KEY_BINDING_", type_id = "meta_key_binding_flags_get_type ()")] [Flags] public enum KeyBindingFlags { NONE, @@ -943,19 +943,19 @@ namespace Meta { REVERSES, IS_REVERSED } - [CCode (cheader_filename = "meta/util.h", cprefix = "META_LATER_")] + [CCode (cheader_filename = "meta/util.h", cprefix = "META_LATER_", type_id = "meta_later_type_get_type ()")] public enum LaterType { RESIZE, BEFORE_REDRAW, IDLE } - [CCode (cheader_filename = "meta/window.h", cprefix = "META_MAXIMIZE_")] + [CCode (cheader_filename = "meta/window.h", cprefix = "META_MAXIMIZE_", type_id = "meta_maximize_flags_get_type ()")] [Flags] public enum MaximizeFlags { HORIZONTAL, VERTICAL } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_MENU_OP_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_MENU_OP_", type_id = "meta_menu_op_get_type ()")] [Flags] public enum MenuOp { NONE, @@ -978,13 +978,13 @@ namespace Meta { MOVE_DOWN, RECOVER } - [CCode (cheader_filename = "meta/meta-plugin.h", cprefix = "META_MODAL_")] + [CCode (cheader_filename = "meta/meta-plugin.h", cprefix = "META_MODAL_", type_id = "meta_modal_options_get_type ()")] [Flags] public enum ModalOptions { POINTER_ALREADY_GRABBED, KEYBOARD_ALREADY_GRABBED } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_MOTION_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_MOTION_", type_id = "meta_motion_direction_get_type ()")] public enum MotionDirection { UP, DOWN, @@ -995,7 +995,7 @@ namespace Meta { DOWN_LEFT, DOWN_RIGHT } - [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_PREF_")] + [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_PREF_", type_id = "meta_preference_get_type ()")] public enum Preference { MOUSE_BUTTON_MODS, FOCUS_MODE, @@ -1032,21 +1032,21 @@ namespace Meta { [CCode (cheader_filename = "meta/main.h")] public static unowned string to_string (Meta.Preference pref); } - [CCode (cheader_filename = "meta/screen.h", cprefix = "META_SCREEN_")] + [CCode (cheader_filename = "meta/screen.h", cprefix = "META_SCREEN_", type_id = "meta_screen_corner_get_type ()")] public enum ScreenCorner { TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_SIDE_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_SIDE_", type_id = "meta_side_get_type ()")] public enum Side { LEFT, RIGHT, TOP, BOTTOM } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_LAYER_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_LAYER_", type_id = "meta_stack_layer_get_type ()")] public enum StackLayer { DESKTOP, BOTTOM, @@ -1058,19 +1058,19 @@ namespace Meta { OVERRIDE_REDIRECT, LAST } - [CCode (cheader_filename = "meta/display.h", cprefix = "META_TAB_LIST_")] + [CCode (cheader_filename = "meta/display.h", cprefix = "META_TAB_LIST_", type_id = "meta_tab_list_get_type ()")] public enum TabList { NORMAL, DOCKS, GROUP, NORMAL_ALL } - [CCode (cheader_filename = "meta/display.h", cprefix = "META_TAB_SHOW_")] + [CCode (cheader_filename = "meta/display.h", cprefix = "META_TAB_SHOW_", type_id = "meta_tab_show_type_get_type ()")] public enum TabShowType { ICON, INSTANTLY } - [CCode (cheader_filename = "meta/common.h", cprefix = "META_VIRTUAL_")] + [CCode (cheader_filename = "meta/common.h", cprefix = "META_VIRTUAL_", type_id = "meta_virtual_modifier_get_type ()")] [Flags] public enum VirtualModifier { SHIFT_MASK, @@ -1084,7 +1084,7 @@ namespace Meta { MOD4_MASK, MOD5_MASK } - [CCode (cheader_filename = "meta/window.h", cprefix = "META_WINDOW_")] + [CCode (cheader_filename = "meta/window.h", cprefix = "META_WINDOW_", type_id = "meta_window_type_get_type ()")] public enum WindowType { NORMAL, DESKTOP, From b5381ca33681fb2b5032f3ac8230e081d71f5765 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Tue, 21 Aug 2012 17:36:23 +0200 Subject: [PATCH 18/46] vapi: update to mutter 3.5.90 --- vapi/libmutter.vapi | 1 + 1 file changed, 1 insertion(+) diff --git a/vapi/libmutter.vapi b/vapi/libmutter.vapi index c76330c5..817586eb 100644 --- a/vapi/libmutter.vapi +++ b/vapi/libmutter.vapi @@ -932,6 +932,7 @@ namespace Meta { MOVE_TO_SIDE_E, MOVE_TO_SIDE_W, MOVE_TO_CENTER, + OVERLAY_KEY, LAST } [CCode (cheader_filename = "meta/prefs.h", cprefix = "META_KEY_BINDING_", type_id = "meta_key_binding_flags_get_type ()")] From b337607279ee7e9add6b53c2a9d895402c75cc00 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Thu, 23 Aug 2012 12:03:20 +0200 Subject: [PATCH 19/46] vapi: sync bamf bindings with plank Rename to libbamf3.vapi to follow upstream --- CMakeLists.txt | 4 +- vapi/bamf.vapi | 168 ---------------------------------------- vapi/libbamf3.vapi | 189 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 170 deletions(-) delete mode 100644 vapi/bamf.vapi create mode 100644 vapi/libbamf3.vapi diff --git a/CMakeLists.txt b/CMakeLists.txt index 72b15b52..75546fd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ add_definitions(-DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\") find_package(PkgConfig) pkg_check_modules(DEPS REQUIRED libmutter granite clutter-1.0 clutter-gtk-1.0 libbamf3 xfixes gee-1.0 libplank) -pkg_check_modules(MUTTER36 libmutter>=3.5.3) +pkg_check_modules(MUTTER36 QUIET libmutter>=3.5.3) if (MUTTER36_FOUND) set (GALAVALAFLAGS "--define=HAS_MUTTER36") endif (MUTTER36_FOUND) @@ -60,13 +60,13 @@ vala_precompile(VALA_C ${CMAKE_BINARY_DIR}/src/Config.vala PACKAGES granite + libbamf3 libmutter plank clutter-gtk-1.0 gdk-x11-3.0 gdesktopenums-3.0 xfixes-4.0 - bamf OPTIONS -g --vapidir=${CMAKE_CURRENT_SOURCE_DIR}/vapi/ diff --git a/vapi/bamf.vapi b/vapi/bamf.vapi deleted file mode 100644 index 8397864e..00000000 --- a/vapi/bamf.vapi +++ /dev/null @@ -1,168 +0,0 @@ -/* bamf.vapi generated by vapigen, do not modify. */ - -[CCode (cprefix = "Bamf", lower_case_cprefix = "bamf_")] -namespace Bamf { - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_APPLICATION")] - public class Application : Bamf.View { - [CCode (has_construct_function = false)] - protected Application (); - public unowned string? get_application_type (); - public unowned string? get_desktop_file (); - public bool get_show_menu_stubs (); - public GLib.List? get_windows (); - public GLib.Array? get_xids (); - public virtual signal void window_added (Bamf.View p0); - public virtual signal void window_removed (Bamf.View p0); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_CONTROL")] - public class Control : GLib.Object { - [CCode (has_construct_function = false)] - protected Control (); - public static unowned Bamf.Control get_default (); - public void insert_desktop_file (string desktop_file); - public void register_application_for_pid (string application, int32 pid); - public void register_tab_provider (string path); - public void set_approver_behavior (int32 behavior); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_INDICATOR")] - public class Indicator : Bamf.View { - [CCode (has_construct_function = false)] - protected Indicator (); - public unowned string? get_dbus_menu_path (); - public unowned string? get_remote_address (); - public unowned string? get_remote_path (); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_MATCHER")] - public class Matcher : GLib.Object { - [CCode (has_construct_function = false)] - protected Matcher (); - public bool application_is_running (string application); - public unowned Bamf.Application? get_active_application (); - public unowned Bamf.Window? get_active_window (); - public unowned Bamf.Application? get_application_for_desktop_file (string desktop_file_path, bool create_if_not_found); - public unowned Bamf.Application? get_application_for_window (Bamf.Window window); - public unowned Bamf.Application? get_application_for_xid (uint32 xid); - public GLib.List? get_applications (); - public static unowned Bamf.Matcher get_default (); - public GLib.List? get_running_applications (); - public GLib.List? get_tabs (); - public GLib.List? get_window_stack_for_monitor (int monitor); - public GLib.List? get_windows (); - public GLib.Array? get_xids_for_application (string application); - public void register_favorites ([CCode (array_length = false)] string[] favorites); - public virtual signal void active_application_changed (Bamf.View? p0, Bamf.View? p1); - public virtual signal void active_window_changed (Bamf.View? p0, Bamf.View? p1); - public virtual signal void stacking_order_changed (); - public virtual signal void view_closed (Bamf.View p0); - public virtual signal void view_opened (Bamf.View p0); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_TAB_SOURCE")] - public class TabSource : GLib.Object { - [CCode (has_construct_function = false)] - protected TabSource (); - public unowned string get_tab_ids (); - public unowned GLib.Array get_tab_preview (string tab_id); - public unowned string get_tab_uri (string tab_id); - public uint32 get_tab_xid (string tab_id); - public virtual void show_tab (string tab_id, GLib.Error error); - [NoWrapper] - public virtual unowned string tab_ids (); - [NoWrapper] - public virtual unowned GLib.Array tab_preview (string tab_id); - [NoWrapper] - public virtual unowned string tab_uri (string tab_id); - [NoWrapper] - public virtual uint32 tab_xid (string tab_id); - [NoAccessorMethod] - public string id { owned get; set construct; } - public virtual signal void tab_closed (string p0); - public virtual signal void tab_opened (string p0); - public virtual signal void tab_uri_changed (string p0, string p1, string p2); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_VIEW")] - public class View : GLib.InitiallyUnowned { - [CCode (has_construct_function = false)] - protected View (); - [NoWrapper] - public virtual Bamf.ClickBehavior click_behavior (); - public virtual GLib.List? get_children (); - public Bamf.ClickBehavior get_click_suggestion (); - public virtual unowned string? get_icon (); - public virtual unowned string? get_name (); - public unowned string? get_view_type (); - public virtual bool is_active (); - public bool is_closed (); - public virtual bool is_running (); - public bool is_sticky (); - public virtual bool is_urgent (); - [CCode (cname = "bamf_view_user_visible")] - public bool is_user_visible (); - [NoWrapper] - public virtual void set_path (string path); - public void set_sticky (bool value); - [NoWrapper] - public virtual unowned string view_type (); - [NoAccessorMethod] - public bool active { get; } - [NoAccessorMethod] - public string path { owned get; } - [NoAccessorMethod] - public bool running { get; } - [NoAccessorMethod] - public bool urgent { get; } - [NoAccessorMethod] - public bool user_visible { get; } - public virtual signal void active_changed (bool active); - public virtual signal void child_added (Bamf.View? child); - public virtual signal void child_removed (Bamf.View? child); - public virtual signal void closed (); - public virtual signal void name_changed (string old_name, string new_name); - public virtual signal void running_changed (bool running); - public virtual signal void urgent_changed (bool urgent); - public virtual signal void user_visible_changed (bool user_visible); - } - [CCode (cheader_filename = "libbamf/libbamf.h", type_check_function = "BAMF_IS_WINDOW")] - public class Window : Bamf.View { - [CCode (has_construct_function = false)] - protected Window (); - public int get_monitor (); - public uint32 get_pid (); - public unowned Bamf.Window? get_transient (); - public unowned string? get_utf8_prop (string prop); - public Bamf.WindowType get_window_type (); - public uint32 get_xid (); - public ulong last_active (); - public Bamf.WindowMaximizationType maximized (); - public virtual signal void maximized_changed (int old_value, int new_value); - public virtual signal void monitor_changed (int old_value, int new_value); - } - [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_CLICK_BEHAVIOR_", has_type_id = false)] - public enum ClickBehavior { - NONE, - OPEN, - FOCUS, - FOCUS_ALL, - MINIMIZE, - RESTORE, - RESTORE_ALL, - PICKER - } - [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_WINDOW_", has_type_id = false)] - public enum WindowMaximizationType { - FLOATING, - HORIZONTAL_MAXIMIZED, - VERTICAL_MAXIMIZED, - MAXIMIZED - } - [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_WINDOW_", has_type_id = false)] - public enum WindowType { - NORMAL, - DESKTOP, - DOCK, - DIALOG, - TOOLBAR, - MENU, - UTILITY, - SPLASHSCREEN - } -} diff --git a/vapi/libbamf3.vapi b/vapi/libbamf3.vapi new file mode 100644 index 00000000..f6f68804 --- /dev/null +++ b/vapi/libbamf3.vapi @@ -0,0 +1,189 @@ +/* libbamf3.vapi generated by vapigen, do not modify. */ + +[CCode (cprefix = "Bamf", gir_namespace = "Bamf", gir_version = "0.2", lower_case_cprefix = "bamf_")] +namespace Bamf { + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_application_get_type ()")] + public class Application : Bamf.View { + [CCode (has_construct_function = false)] + protected Application (); + public unowned string get_application_type (); + public unowned string get_desktop_file (); + public bool get_show_menu_stubs (); + public GLib.List get_windows (); + public GLib.Array get_xids (); + public signal void window_added (Bamf.View object); + public signal void window_removed (Bamf.View object); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_control_get_type ()")] + public class Control : GLib.Object { + [CCode (has_construct_function = false)] + protected Control (); + public void insert_desktop_file (string desktop_file); + public void register_application_for_pid (string application, int32 pid); + public void register_tab_provider (string path); + public void set_approver_behavior (int32 behavior); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_factory_get_type ()")] + public class Factory : GLib.Object { + [CCode (has_construct_function = false)] + protected Factory (); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_indicator_get_type ()")] + public class Indicator : Bamf.View { + [CCode (has_construct_function = false)] + protected Indicator (); + public unowned string get_dbus_menu_path (); + public unowned string get_remote_address (); + public unowned string get_remote_path (); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_matcher_get_type ()")] + public class Matcher : GLib.Object { + [CCode (has_construct_function = false)] + protected Matcher (); + public bool application_is_running (string application); + public unowned Bamf.Application get_active_application (); + public unowned Bamf.Window get_active_window (); + public unowned Bamf.Application get_application_for_desktop_file (string desktop_file_path, bool create_if_not_found); + public unowned Bamf.Application get_application_for_window (Bamf.Window window); + public unowned Bamf.Application get_application_for_xid (uint32 xid); + public GLib.List get_applications (); + public static Bamf.Matcher get_default (); + public GLib.List get_running_applications (); + public GLib.List get_tabs (); + public GLib.List get_window_stack_for_monitor (int monitor); + public GLib.List get_windows (); + public GLib.Array get_xids_for_application (string application); + public void register_favorites ([CCode (array_length = false)] string[] favorites); + public signal void active_application_changed (Bamf.View p0, Bamf.View p1); + public signal void active_window_changed (Bamf.View p0, Bamf.View p1); + public signal void stacking_order_changed (); + public signal void view_closed (Bamf.View p0); + public signal void view_opened (Bamf.View p0); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_tab_get_type ()")] + public class Tab : Bamf.View { + [CCode (has_construct_function = false)] + public Tab (string id, string uri); + public string get_id (); + public string get_preview (); + public string get_uri (); + public void set_preview (string uri); + public void set_uri (string uri); + public virtual void show (); + [NoAccessorMethod] + public string id { owned get; set construct; } + public string preview { owned get; set; } + public string uri { owned get; set construct; } + public virtual signal void preview_updated (); + public virtual signal void uri_changed (string new_uri, string p0); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_tab_source_get_type ()")] + public class TabSource : GLib.Object { + [CCode (has_construct_function = false)] + protected TabSource (); + public string get_tab_uri (string tab_id); + public uint32 get_tab_xid (string tab_id); + [NoWrapper] + public virtual string tab_uri (string tab_id); + [NoWrapper] + public virtual uint32 tab_xid (string tab_id); + [NoAccessorMethod] + public string id { owned get; set construct; } + public signal void tab_closed (string object); + public signal void tab_opened (string object); + public signal void tab_uri_changed (string object, string p0, string p1); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_view_get_type ()")] + public class View : GLib.InitiallyUnowned { + [CCode (has_construct_function = false)] + protected View (); + [NoWrapper] + public virtual Bamf.ClickBehavior click_behavior (); + public virtual GLib.List get_children (); + public Bamf.ClickBehavior get_click_suggestion (); + public virtual string get_icon (); + public virtual string get_name (); + [CCode (vfunc_name = "view_type")] + public virtual unowned string get_view_type (); + public virtual bool is_active (); + public bool is_closed (); + public virtual bool is_running (); + public bool is_sticky (); + public virtual bool is_urgent (); + [CCode (cname = "bamf_view_user_visible")] + public bool is_user_visible (); + [NoWrapper] + public virtual void set_path (string path); + public void set_sticky (bool value); + [NoAccessorMethod] + public bool active { get; } + [NoAccessorMethod] + public string path { owned get; } + [NoAccessorMethod] + public bool running { get; } + [NoAccessorMethod] + public bool urgent { get; } + [NoAccessorMethod] + public bool user_visible { get; } + public virtual signal void active_changed (bool active); + public virtual signal void child_added (Bamf.View child); + public virtual signal void child_removed (Bamf.View child); + public virtual signal void closed (); + public virtual signal void name_changed (string old_name, string new_name); + public virtual signal void running_changed (bool running); + public virtual signal void urgent_changed (bool urgent); + public virtual signal void user_visible_changed (bool user_visible); + } + [CCode (cheader_filename = "libbamf/libbamf.h", type_id = "bamf_window_get_type ()")] + public class Window : Bamf.View { + [CCode (has_construct_function = false)] + protected Window (); + public int get_monitor (); + public uint32 get_pid (); + public unowned Bamf.Window get_transient (); + public string get_utf8_prop (string prop); + public Bamf.WindowType get_window_type (); + public uint32 get_xid (); + public long last_active (); + public Bamf.WindowMaximizationType maximized (); + public virtual signal void maximized_changed (int old_value, int new_value); + public virtual signal void monitor_changed (int old_value, int new_value); + } + [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_CLICK_BEHAVIOR_")] + public enum ClickBehavior { + NONE, + OPEN, + FOCUS, + FOCUS_ALL, + MINIMIZE, + RESTORE, + RESTORE_ALL, + PICKER + } + [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_FACTORY_")] + public enum FactoryViewType { + VIEW, + WINDOW, + APPLICATION, + INDICATOR, + NONE + } + [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_WINDOW_")] + public enum WindowMaximizationType { + FLOATING, + HORIZONTAL_MAXIMIZED, + VERTICAL_MAXIMIZED, + MAXIMIZED + } + [CCode (cheader_filename = "libbamf/libbamf.h", cprefix = "BAMF_WINDOW_")] + public enum WindowType { + NORMAL, + DESKTOP, + DOCK, + DIALOG, + TOOLBAR, + MENU, + UTILITY, + SPLASHSCREEN + } +} From abaa31dfa84d98c9df462f973403b035a08333fb Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 23 Aug 2012 15:08:23 +0200 Subject: [PATCH 20/46] Fix expose algorithm, add comments from the GS extension --- src/Expo.vala | 122 +++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 51 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index c4e4e29d..b5d8d124 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -65,12 +65,12 @@ namespace Gala const int MAX_TRANSLATIONS = 5000; const int ACCURACY = 20; const int BORDER = 10; - const int TOP = 20; + const int TOP_GAP = 20; const bool use_more_screen = true; int[] rect_center (Meta.Rectangle rect) { - return {rect.width / 2, rect.height / 2}; + return {rect.x + rect.width / 2, rect.y + rect.height / 2}; } Meta.Rectangle rect_adjusted (Meta.Rectangle rect, int dx1, int dy1, int dx2, int dy2) { @@ -84,78 +84,93 @@ namespace Gala return (int)(a as ExposedWindow).window.get_stable_sequence () - (int)(b as ExposedWindow).window.get_stable_sequence (); }); - //get a working area - var monitor = screen.get_monitor_geometry (screen.get_primary_monitor ()); - var ratio = monitor.width / (float)monitor.height; - var x_gap = Math.fmaxf (BORDER, TOP * ratio); - var y_gap = Math.fmaxf (BORDER / ratio, TOP); - Meta.Rectangle area = {(int)Math.floorf (monitor.x + x_gap / 2), - (int)Math.floorf (monitor.y + y_gap / 2), - (int)Math.floorf (monitor.width - x_gap), - (int)Math.floorf (monitor.height - y_gap)}; + // Put a gap on the right edge of the workspace to separe it from the workspace selector + var geom = screen.get_monitor_geometry (screen.get_primary_monitor ()); + var ratio = geom.width / (float)geom.height; + var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); + var y_gap = Math.fmaxf (BORDER / ratio, TOP_GAP); + Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), + (int)Math.floorf (geom.y + 20 + y_gap), + (int)Math.floorf (geom.width - x_gap), + (int)Math.floorf (geom.height - 80 - y_gap)}; - //get a copy Meta.Rectangle bounds = {area.x, area.y, area.width, area.height}; var direction = 0; var directions = new List (); var rects = new List (); - foreach (var clone in clones) { - var rect = (clone as ExposedWindow).window.get_outer_rect (); - rects.append (rect); - bounds = bounds.union (rect); + 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] + var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); + rects.append ({rect.x, rect.y, rect.width, rect.height}); + 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. directions.append (direction); direction ++; - if (direction == 4) + if (direction == 4) { direction = 0; + } } - int loop_counter = 0; - bool overlap = false; + var loop_counter = 0; + var overlap = false; do { overlap = false; - for (var i=0;i area.height / (float)area.width) + // Try to keep screen/workspace aspect ratio + if (bounds.height / bounds.width > area.height / area.width) diff[0] *= 2; else diff[1] *= 2; + // Approximate a vector of between 10px and 20px in magnitude in the same direction var length = Math.sqrtf (diff[0] * diff[0] + diff[1] * diff[1]); diff[0] = (int)Math.floorf (diff[0] * ACCURACY / length); diff[1] = (int)Math.floorf (diff[1] * ACCURACY / length); + // Move both windows apart rects.nth_data (i).x += -diff[0]; rects.nth_data (i).y += -diff[1]; rects.nth_data (j).x += diff[0]; rects.nth_data (j).y += diff[1]; if (use_more_screen) { - var x_section = Math.round ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); - var y_section = Math.round ((rects.nth_data (i).y - bounds.y) / (bounds.height / 3.0f)); - + // Try to keep the bounding rect the same aspect as the screen so that more + // 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 + // window towards the outer corner. If it is in any of the other edge sections + // alternate between each corner on that edge. We don't want to determine it + // randomly as it will not produce consistant locations when using the filter. + // Only move one window so we don't cause large amounts of unnecessary zooming + // in some situations. We need to do this even when expanding later just in case + // all windows are the same size. + // (We are using an old bounding rect for this, hopefully it doesn't matter) + var x_section = Math.roundf ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); + var y_section = Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); + i_center = rect_center (rects.nth_data (i)); diff[0] = 0; diff[1] = 0; - if (x_section != 1 || y_section != 1) { + if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well if (x_section == 1) - x_section = directions.nth_data (i) / 2 == 1 ? 2 : 0; + x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); if (y_section == 1) - y_section = directions.nth_data (i) % 2 == 1 ? 2 : 0; + y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); } if (x_section == 0 && y_section == 0) { diff[0] = bounds.x - i_center[0]; @@ -174,45 +189,50 @@ namespace Gala diff[1] = bounds.y + bounds.height - i_center[1]; } if (diff[0] != 0 || diff[1] != 0) { - length = Math.sqrtf (diff[0] * diff[0] + diff[1] * diff[1]); - diff[0] *= (int)Math.floorf (ACCURACY / length / 2.0f); + length = Math.sqrtf (diff[0]*diff[0] + diff[1]*diff[1]); + diff[0] *= (int)Math.floorf (ACCURACY / length / 2.0f); // /2 to make it less influencing than the normal center-move above diff[1] *= (int)Math.floorf (ACCURACY / length / 2.0f); rects.nth_data (i).x += diff[0]; rects.nth_data (i).y += diff[1]; } } - bounds = bounds.union (rects.nth_data (i)); - bounds = bounds.union (rects.nth_data (j)); + // Update bounding rect + bounds = bounds.union(rects.nth_data (i)); + bounds = bounds.union(rects.nth_data (j)); } } } } while (overlap && loop_counter < MAX_TRANSLATIONS); - var scale = Math.fminf (Math.fminf (area.width / (float)bounds.width, area.height / (float)bounds.height), 1.0f); - bounds.x = (int)Math.floorf (bounds.x - (area.width - bounds.width * scale) / 2.0f); - bounds.y = (int)Math.floorf (bounds.y - (area.height - bounds.height * scale) / 2.0f); + // Work out scaling by getting the most top-left and most bottom-right window coords. + float scale = Math.fminf (Math.fminf (area.width / (float)bounds.width, area.height / (float)bounds.height), 1.0f); + + // Make bounding rect fill the screen size for later steps + bounds.x = (int)Math.floorf (bounds.x - (area.width - bounds.width * scale) / 2); + bounds.y = (int)Math.floorf (bounds.y - (area.height - bounds.height * scale) / 2); bounds.width = (int)Math.floorf (area.width / scale); bounds.height = (int)Math.floorf (area.height / scale); - foreach (var rect in rects) { - rect.x += -bounds.x; - rect.y += -bounds.y; + // Move all windows back onto the screen and set their scale + for (var i = 0; i < rects.length (); i++) { + rects.nth_data (i).x += -bounds.x; + rects.nth_data (i).y += -bounds.y; } - for (var i=0;i ready = true ); clone.icon.opacity = 0; clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); From ba68b361fae6ae6d9e581b4c79e335e5cecd085e Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 23 Aug 2012 15:42:34 +0200 Subject: [PATCH 21/46] Do some adjustments, add close button --- src/Expo.vala | 17 +++++-- src/Widgets/ExposedWindow.vala | 81 +++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index b5d8d124..68168f2e 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -61,7 +61,7 @@ namespace Gala * Code borrowed from native window placement GS extension * http://git.gnome.org/browse/gnome-shell-extensions/tree/extensions/native-window-placement/extension.js **/ - const int GAPS = 5; + const int GAPS = 15; const int MAX_TRANSLATIONS = 5000; const int ACCURACY = 20; const int BORDER = 10; @@ -92,7 +92,7 @@ namespace Gala Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), (int)Math.floorf (geom.y + 20 + y_gap), (int)Math.floorf (geom.width - x_gap), - (int)Math.floorf (geom.height - 80 - y_gap)}; + (int)Math.floorf (geom.height - 100 - y_gap)}; Meta.Rectangle bounds = {area.x, area.y, area.width, area.height}; @@ -229,9 +229,12 @@ namespace Gala //animate the windows and icons to the calculated positions clone.icon.x = rects.nth_data (i).x + Math.floorf (clone.width * scale / 2.0f - clone.icon.width / 2.0f); - clone.icon.y = rects.nth_data (i).y + Math.floorf (clone.height * scale - 30.0f); + clone.icon.y = rects.nth_data (i).y + Math.floorf (clone.height * scale - 50.0f); clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); + clone.close_button.x = rects.nth_data (i).x - 12; + clone.close_button.y = rects.nth_data (i).y - 12; + clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:scale, scale_y:scale, x:rects.nth_data (i).x+0.0f, y:rects.nth_data (i).y+0.0f) .completed.connect (() => ready = true ); clone.icon.opacity = 0; @@ -284,6 +287,7 @@ namespace Gala clone.y = actor.y; clone.selected.connect (selected); + clone.reposition.connect (reposition); add_child (clone); } @@ -291,6 +295,13 @@ namespace Gala calculate_places (get_children ()); } + void reposition (ExposedWindow removed) + { + var children = get_children ().copy (); + children.remove (removed); + calculate_places (children); + } + void selected (Window window) { window.activate (screen.get_display ().get_current_time ()); diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index c3d01a8d..0cf9f856 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -16,16 +16,19 @@ // using Meta; +using Clutter; namespace Gala { - public class ExposedWindow : Clutter.Actor + public class ExposedWindow : Actor { public weak Window window; - Clutter.Clone clone; + Clone clone; public GtkClutter.Texture icon; + public GtkClutter.Texture close_button; public signal void selected (Window window); + public signal void reposition (); public ExposedWindow (Window _window) { @@ -34,23 +37,77 @@ namespace Gala reactive = true; var actor = window.get_compositor_private () as WindowActor; - clone = new Clutter.Clone (actor.get_texture ()); + clone = new Clone (actor.get_texture ()); icon = new GtkClutter.Texture (); icon.scale_x = 0.0f; icon.scale_y = 0.0f; - icon.scale_gravity = Clutter.Gravity.CENTER; + icon.scale_gravity = Gravity.CENTER; try { icon.set_from_pixbuf (Utils.get_icon_for_window (window, 64)); } catch (Error e) { warning (e.message); } + close_button = new GtkClutter.Texture (); + close_button.reactive = true; + close_button.visible = false; + close_button.scale_x = 0.0f; + close_button.scale_y = 0.0f; + close_button.scale_gravity = Gravity.CENTER; + close_button.button_press_event.connect (close_clicked); + + try { + close_button.set_from_pixbuf (Granite.Widgets.get_close_pixbuf ()); + } catch (Error e) { warning (e.message); } + add_child (clone); - Compositor.get_stage_for_screen (window.get_screen ()).add_child (icon); + var stage = Compositor.get_stage_for_screen (window.get_screen ()); + stage.add_child (icon); + stage.add_child (close_button); } - public override bool button_press_event (Clutter.ButtonEvent event) + bool close_clicked (ButtonEvent event) + { + if (event.button != 1) + return false; + + //make sure we dont see a window closing animation in the background + (window.get_compositor_private () as Actor).opacity = 0; + get_parent ().set_child_below_sibling (this, null); + animate (AnimationMode.EASE_IN_CUBIC, 200, depth : -50.0f, opacity : 0).completed.connect (() => { + destroy (); + window.delete (window.get_screen ().get_display ().get_current_time ()); + }); + + close_button.destroy (); + icon.destroy (); + + reposition (); + + return true; + } + + public override bool enter_event (CrossingEvent event) + { + close_button.visible = true; + close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f); + + return true; + } + + public override bool leave_event (CrossingEvent event) + { + if (event.related == close_button) + return false; + + close_button.animate (AnimationMode.EASE_IN_QUAD, 400, scale_x : 0.0f, scale_y : 0.0f) + .completed.connect (() => close_button.visible = false ); + + return true; + } + + public override bool button_press_event (ButtonEvent event) { get_parent ().set_child_above_sibling (this, null); selected (window); @@ -60,7 +117,7 @@ namespace Gala public void close (bool do_animate=true) { - unowned Rectangle rect = window.get_outer_rect (); + unowned Meta.Rectangle rect = window.get_outer_rect (); //FIXME need to subtract 10 here to remove jump for most windows, but adds jump for maximized ones float delta = window.maximized_horizontally || window.maximized_vertically ? 0 : 10; @@ -73,20 +130,22 @@ namespace Gala icon.detach_animation (); if (do_animate) { - icon.animate (Clutter.AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f).completed.connect ( () => { + icon.animate (AnimationMode.EASE_IN_CUBIC, 100, scale_x:0.0f, scale_y:0.0f).completed.connect ( () => { icon.destroy (); }); - animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { - (window.get_compositor_private () as Clutter.Actor).show (); + animate (AnimationMode.EASE_OUT_CUBIC, 250, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { + (window.get_compositor_private () as Actor).show (); destroy (); }); } else { - (window.get_compositor_private () as Clutter.Actor).show (); + (window.get_compositor_private () as Actor).show (); destroy (); icon.destroy (); } + + close_button.destroy (); } } } From cc6ad64fdcbc3064abedb91e7650121398c5d5ac Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Thu, 23 Aug 2012 15:53:45 +0200 Subject: [PATCH 22/46] Move close button down --- src/Expo.vala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 68168f2e..7c3182b7 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -232,8 +232,8 @@ namespace Gala clone.icon.y = rects.nth_data (i).y + Math.floorf (clone.height * scale - 50.0f); clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); - clone.close_button.x = rects.nth_data (i).x - 12; - clone.close_button.y = rects.nth_data (i).y - 12; + clone.close_button.x = rects.nth_data (i).x - 10; + clone.close_button.y = rects.nth_data (i).y - 10; clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:scale, scale_y:scale, x:rects.nth_data (i).x+0.0f, y:rects.nth_data (i).y+0.0f) .completed.connect (() => ready = true ); From e858a0d5fd08503060ff9ef63994f14414f2fc83 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 09:05:34 +0200 Subject: [PATCH 23/46] Fix window icon repositioning after DnD --- src/Widgets/AppIcon.vala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Widgets/AppIcon.vala b/src/Widgets/AppIcon.vala index 411365d2..cebccdce 100644 --- a/src/Widgets/AppIcon.vala +++ b/src/Widgets/AppIcon.vala @@ -62,15 +62,12 @@ namespace Gala } else { WorkspaceThumb old = actor.get_parent ().get_parent () as WorkspaceThumb; actor.get_parent ().remove_child (actor); - if (old != null) - old.icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (old.wallpaper.x + old.wallpaper.width / 2 - old.icons.width / 2)); actor.opacity = 255; var icons = (WorkspaceThumb.destination as WorkspaceThumb).icons; var wallpaper = (WorkspaceThumb.destination as WorkspaceThumb).wallpaper; icons.add_child (actor); - icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (wallpaper.x + wallpaper.width / 2 - icons.width / 2)); var xids = app.get_xids (); if (xids.length > 1) { //get all the windows that belong to this app @@ -86,6 +83,10 @@ namespace Gala if (handle != null) handle.destroy (); + + if (old != null) + old.icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (old.wallpaper.x + old.wallpaper.width / 2 - old.icons.width / 2)); + icons.animate (AnimationMode.LINEAR, 100, x:Math.floorf (wallpaper.x + wallpaper.width / 2 - icons.width / 2)); } } From f84c1860758ec43b6d0a1a7eeadb84af7f3c02ad Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 14:54:16 +0200 Subject: [PATCH 24/46] Possibly fixed update manager crash --- src/Plugin.vala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index f9a4212e..0ccef648 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -296,6 +296,9 @@ namespace Gala minimize_completed (actor); return; } + + kill_window_effects (actor); + int width, height; get_screen ().get_size (out width, out height); @@ -571,9 +574,10 @@ namespace Gala public override void kill_window_effects (WindowActor actor) { - if (end_animation (ref mapping, actor)) + if (end_animation (ref mapping, actor)) { map_completed (actor); - if (end_animation (ref minimizing, actor)) + print ("Killed map animation\n"); + } if (end_animation (ref minimizing, actor)) minimize_completed (actor); if (end_animation (ref maximizing, actor)) maximize_completed (actor); From 9ccfdf26871efa2ee96ca72a7fd0f8283343c932 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 15:19:22 +0200 Subject: [PATCH 25/46] Improve animations --- src/Expo.vala | 2 +- src/Widgets/ExposedWindow.vala | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index b0666c94..9304a510 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -331,7 +331,7 @@ namespace Gala } if (animate) { - Timeout.add (250, () => { + Timeout.add (300, () => { visible = false; ready = true; diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index 0cf9f856..b61e2ab5 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -55,6 +55,7 @@ namespace Gala close_button.scale_y = 0.0f; close_button.scale_gravity = Gravity.CENTER; close_button.button_press_event.connect (close_clicked); + close_button.leave_event.connect ((e) => leave_event (e)); try { close_button.set_from_pixbuf (Granite.Widgets.get_close_pixbuf ()); @@ -90,6 +91,21 @@ namespace Gala public override bool enter_event (CrossingEvent event) { + //if we're still animating don't show the close button + if (get_animation () != null) + return false; + + close_button.visible = true; + close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f); + + return true; + } + + public override bool motion_event (MotionEvent event) + { + if (get_animation () != null) + return false; + close_button.visible = true; close_button.animate (AnimationMode.EASE_OUT_ELASTIC, 400, scale_x : 1.0f, scale_y : 1.0f); @@ -134,7 +150,7 @@ namespace Gala icon.destroy (); }); - animate (AnimationMode.EASE_OUT_CUBIC, 250, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { + animate (AnimationMode.EASE_IN_OUT_CUBIC, 300, scale_x:1.0f, scale_y:1.0f, x:dest_x, y:dest_y).completed.connect (() => { (window.get_compositor_private () as Actor).show (); destroy (); }); From d3ac01c51b205bc8e1bcfa99c64a0b8839559e7b Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 15:23:57 +0200 Subject: [PATCH 26/46] Darken background while being in expose --- src/Expo.vala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Expo.vala b/src/Expo.vala index 9304a510..7f5568f3 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -256,6 +256,9 @@ namespace Gala var used_windows = new SList (); + 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 ()) { if (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DOCK) { (window.get_compositor_private () as Actor).hide (); @@ -330,6 +333,9 @@ namespace Gala exposed.selected.disconnect (selected); } + Compositor.get_background_actor_for_screen (screen). + animate (AnimationMode.EASE_OUT_QUAD, 500, dim_factor : 1.0); + if (animate) { Timeout.add (300, () => { visible = false; From bcbc38413fc454584543061db5b11206d5ecf586 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 20:10:35 +0200 Subject: [PATCH 27/46] Add a second, grid based algorithm, make this one the default one and add options in dconf to switch it --- data/org.pantheon.desktop.gala.gschema.xml | 9 + src/Expo.vala | 237 ++++++++++++++++----- src/Settings.vala | 2 + 3 files changed, 191 insertions(+), 57 deletions(-) diff --git a/data/org.pantheon.desktop.gala.gschema.xml b/data/org.pantheon.desktop.gala.gschema.xml index e162a816..705276a4 100644 --- a/data/org.pantheon.desktop.gala.gschema.xml +++ b/data/org.pantheon.desktop.gala.gschema.xml @@ -9,6 +9,10 @@ + + + + @@ -16,6 +20,11 @@ Action for the top left corner + + 'grid' + Algorithm for window overview layout + Choose the algorithm used for exposing the windows + 'none' Action for the top right corner diff --git a/src/Expo.vala b/src/Expo.vala index 7f5568f3..75d30a44 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -20,6 +20,13 @@ using Clutter; namespace Gala { + + public enum WindowOverviewType + { + GRID = 0, + NATURAL + } + public class Expo : Actor { Plugin plugin; @@ -58,17 +65,24 @@ namespace Gala } /** - * Code borrowed from native window placement GS extension - * http://git.gnome.org/browse/gnome-shell-extensions/tree/extensions/native-window-placement/extension.js + * Code taken from KWin present windows effect + * https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp + * **/ - const int GAPS = 15; - const int MAX_TRANSLATIONS = 5000; - const int ACCURACY = 20; + const int GAPS = 20; + const int MAX_TRANSLATIONS = 100000; + const int ACCURACY = 1; const int BORDER = 10; const int TOP_GAP = 20; - const bool use_more_screen = true; + const bool use_more_screen = false; - int[] rect_center (Meta.Rectangle rect) + struct Point + { + int x; + int y; + } + + Point rect_center (Meta.Rectangle rect) { return {rect.x + rect.width / 2, rect.y + rect.height / 2}; } @@ -76,6 +90,16 @@ namespace Gala { return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)}; } + Meta.Rectangle rect_translate (Meta.Rectangle rect, int x, int y) + { + return {rect.x + x, rect.y + y, rect.width, rect.height}; + } + float point_distance (Point a, Point b) + { + var k1 = b.x - a.x; + var k2 = b.y - a.y; + return Math.sqrtf (k1*k1 + k2*k2); + } void calculate_places (List windows) { @@ -90,10 +114,123 @@ namespace Gala var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); var y_gap = Math.fmaxf (BORDER / ratio, TOP_GAP); Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), - (int)Math.floorf (geom.y + 20 + y_gap), + (int)Math.floorf (geom.y + TOP_GAP + y_gap), (int)Math.floorf (geom.width - x_gap), (int)Math.floorf (geom.height - 100 - y_gap)}; + if (BehaviorSettings.get_default ().schema.get_enum ("window-overview-type") == WindowOverviewType.GRID) + grid_placement (area, clones); + else + natural_placement (area, clones); + } + + public void place_window (ExposedWindow clone, Meta.Rectangle rect) + { + var fscale = rect.width / clone.width; + + //animate the windows and icons to the calculated positions + clone.icon.x = rect.x + Math.floorf (clone.width * fscale / 2.0f - clone.icon.width / 2.0f); + clone.icon.y = rect.y + Math.floorf (clone.height * fscale - 50.0f); + clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); + + clone.close_button.x = rect.x - 10; + clone.close_button.y = rect.y - 10; + + clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:fscale, scale_y:fscale, x:rect.x+0.0f, y:rect.y+0.0f) + .completed.connect (() => ready = true ); + clone.icon.opacity = 0; + clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); + } + + void grid_placement (Meta.Rectangle area, List clones) + { + int columns = (int)Math.ceil (Math.sqrt (clones.length ())); + int rows = (int)Math.ceil (clones.length () / (double)columns); + + // Assign slots + int slot_width = area.width / columns; + int slot_height = area.height / rows; + ExposedWindow[] taken_slots = {}; + taken_slots.resize (rows * columns); + + // precalculate all slot centers + 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 + var tmplist = clones.copy (); // use a QLinkedList copy instead? + while (tmplist.length () > 0) { + var w = tmplist.nth_data (0) as ExposedWindow; + var r = w.window.get_outer_rect (); + int slot_candidate = -1; + int slot_candidate_distance = int.MAX; + var pos = rect_center (r); + for (int i = 0; i < columns * rows; i++) { // all slots + int dist = (int)point_distance (pos, slot_centers[i]); + if (dist < slot_candidate_distance) { // window is interested in this slot + ExposedWindow occupier = taken_slots[i]; + if (occupier == w) + continue; + if (occupier == null || dist < point_distance(rect_center (occupier.window.get_outer_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) + tmplist.prepend (taken_slots[slot_candidate]); // occupier needs a new home now :p + tmplist.remove_all(w); + taken_slots[slot_candidate] = w; // ...and we rumble in =) + } + + for (int slot = 0; slot < columns * rows; slot++) { + ExposedWindow w = taken_slots[slot]; + if (w == null) // some slots might be empty + continue; + var r = w.window.get_outer_rect (); + + // Work out where the slot is + Meta.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); // Borders + float scale; + if (target.width / (double)r.width < target.height / (double)r.height) { + // Center vertically + scale = target.width / (float)r.width; + target = rect_translate (target, 0, (target.y + (target.height - (int)(r.height * scale)) / 2) - target.y); + target.height = (int)Math.floorf (r.height * scale); + } else { + // Center horizontally + scale = target.height / (float)w.height; + target = rect_translate (target, (target.x + (target.width - (int)(r.width * scale)) / 2) - target.x, 0); + target.width = (int)Math.floorf (r.width * scale); + } + + // Don't scale the windows too much + if (scale > 2.0 || (scale > 1.0 && (r.width > 300 || r.height > 300))) { + scale = (r.width > 300 || r.height > 300) ? 1.0f : 2.0f; + target = {rect_center (target).x - (int)Math.floorf (r.width * scale) / 2, + rect_center (target).y - (int)Math.floorf (r.height * scale) / 2, + (int)Math.floorf (scale * r.width), + (int)Math.floorf (scale * r.height)}; + } + + place_window (w, target); + } + } + + void natural_placement (Meta.Rectangle area, List clones) + { Meta.Rectangle bounds = {area.x, area.y, area.width, area.height}; var direction = 0; @@ -125,29 +262,29 @@ namespace Gala overlap = true; // Determine pushing direction - int[] i_center = rect_center (rects.nth_data (i)); - int[] j_center = rect_center (rects.nth_data (j)); - int[] diff = {j_center[0] - i_center[0], j_center[1] - i_center[1]}; + Point i_center = rect_center (rects.nth_data (i)); + Point j_center = rect_center (rects.nth_data (j)); + Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; // Prevent dividing by zero and non-movement - if (diff[0] == 0 && diff[1] == 0) - diff[0] = 1; + if (diff.x == 0 && diff.y == 0) + diff.x = 1; // Try to keep screen/workspace aspect ratio if (bounds.height / bounds.width > area.height / area.width) - diff[0] *= 2; + diff.x *= 2; else - diff[1] *= 2; + diff.y *= 2; // Approximate a vector of between 10px and 20px in magnitude in the same direction - var length = Math.sqrtf (diff[0] * diff[0] + diff[1] * diff[1]); - diff[0] = (int)Math.floorf (diff[0] * ACCURACY / length); - diff[1] = (int)Math.floorf (diff[1] * ACCURACY / length); + var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y); + diff.x = (int)Math.floorf (diff.x * ACCURACY / length); + diff.y = (int)Math.floorf (diff.y * ACCURACY / length); // Move both windows apart - rects.nth_data (i).x += -diff[0]; - rects.nth_data (i).y += -diff[1]; - rects.nth_data (j).x += diff[0]; - rects.nth_data (j).y += diff[1]; + rects.nth_data (i).x += -diff.x; + rects.nth_data (i).y += -diff.y; + rects.nth_data (j).x += diff.x; + rects.nth_data (j).y += diff.y; if (use_more_screen) { // Try to keep the bounding rect the same aspect as the screen so that more @@ -162,10 +299,10 @@ namespace Gala // (We are using an old bounding rect for this, hopefully it doesn't matter) var x_section = Math.roundf ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); var y_section = Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); - + i_center = rect_center (rects.nth_data (i)); - diff[0] = 0; - diff[1] = 0; + diff.x = 0; + diff.y = 0; if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well if (x_section == 1) x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); @@ -173,27 +310,27 @@ namespace Gala y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); } if (x_section == 0 && y_section == 0) { - diff[0] = bounds.x - i_center[0]; - diff[1] = bounds.y - i_center[1]; + diff.x = bounds.x - i_center.x; + diff.y = bounds.y - i_center.y; } if (x_section == 2 && y_section == 0) { - diff[0] = bounds.x + bounds.width - i_center[0]; - diff[1] = bounds.y - i_center[1]; + diff.x = bounds.x + bounds.width - i_center.x; + diff.y = bounds.y - i_center.y; } if (x_section == 2 && y_section == 2) { - diff[0] = bounds.x + bounds.width - i_center[0]; - diff[1] = bounds.y + bounds.height - i_center[1]; + 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[0] = bounds.x - i_center[0]; - diff[1] = bounds.y + bounds.height - i_center[1]; + diff.x = bounds.x - i_center.x; + diff.y = bounds.y + bounds.height - i_center.y; } - if (diff[0] != 0 || diff[1] != 0) { - length = Math.sqrtf (diff[0]*diff[0] + diff[1]*diff[1]); - diff[0] *= (int)Math.floorf (ACCURACY / length / 2.0f); // /2 to make it less influencing than the normal center-move above - diff[1] *= (int)Math.floorf (ACCURACY / length / 2.0f); - rects.nth_data (i).x += diff[0]; - rects.nth_data (i).y += diff[1]; + 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; } } @@ -218,27 +355,13 @@ namespace Gala for (var i = 0; i < rects.length (); i++) { rects.nth_data (i).x += -bounds.x; rects.nth_data (i).y += -bounds.y; - } - - - for (var i = 0; i < rects.length (); i++) { + rects.nth_data (i).x = (int)Math.floorf (rects.nth_data (i).x * scale + area.x); rects.nth_data (i).y = (int)Math.floorf (rects.nth_data (i).y * scale + area.y); + rects.nth_data (i).width = (int)Math.floorf (rects.nth_data (i).width * scale); + rects.nth_data (i).height = (int)Math.floorf (rects.nth_data (i).height * scale); - var clone = clones.nth_data (i) as ExposedWindow; - - //animate the windows and icons to the calculated positions - clone.icon.x = rects.nth_data (i).x + Math.floorf (clone.width * scale / 2.0f - clone.icon.width / 2.0f); - clone.icon.y = rects.nth_data (i).y + Math.floorf (clone.height * scale - 50.0f); - clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); - - clone.close_button.x = rects.nth_data (i).x - 10; - clone.close_button.y = rects.nth_data (i).y - 10; - - clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:scale, scale_y:scale, x:rects.nth_data (i).x+0.0f, y:rects.nth_data (i).y+0.0f) - .completed.connect (() => ready = true ); - clone.icon.opacity = 0; - clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); + place_window (clones.nth_data (i) as ExposedWindow, rects.nth_data (i)); } } diff --git a/src/Settings.vala b/src/Settings.vala index 4db61a5f..fd290f49 100644 --- a/src/Settings.vala +++ b/src/Settings.vala @@ -25,6 +25,8 @@ namespace Gala public string overlay_action { get; set; } public string hotcorner_custom_command { get; set; } + public WindowOverviewType window_overview_type { get; set; } + public ActionType hotcorner_topleft { get; set; } public ActionType hotcorner_topright { get; set; } public ActionType hotcorner_bottomleft { get; set; } From 0e596dfe0b0609e63f609e09127cb295b5883bce Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Fri, 24 Aug 2012 21:39:01 +0200 Subject: [PATCH 28/46] Cleaned up rev197 --- src/Plugin.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index 0ccef648..710f8894 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -576,8 +576,10 @@ namespace Gala { if (end_animation (ref mapping, actor)) { map_completed (actor); + //FIXME adding a print here seems to solve bug #1029609 print ("Killed map animation\n"); - } if (end_animation (ref minimizing, actor)) + } + if (end_animation (ref minimizing, actor)) minimize_completed (actor); if (end_animation (ref maximizing, actor)) maximize_completed (actor); From 7dae5e002e27eae48594f8e05ca4b765e19d6583 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 01:01:48 +0200 Subject: [PATCH 29/46] Cleanup natural_placement --- src/Expo.vala | 204 ++++++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/src/Expo.vala b/src/Expo.vala index 75d30a44..91f30bc1 100644 --- a/src/Expo.vala +++ b/src/Expo.vala @@ -74,7 +74,6 @@ namespace Gala const int ACCURACY = 1; const int BORDER = 10; const int TOP_GAP = 20; - const bool use_more_screen = false; struct Point { @@ -98,17 +97,19 @@ namespace Gala { var k1 = b.x - a.x; var k2 = b.y - a.y; - return Math.sqrtf (k1*k1 + k2*k2); + + return k1*k1 + k2*k2; } void calculate_places (List windows) { var clones = windows.copy (); 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 ratio = geom.width / (float)geom.height; var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); @@ -156,11 +157,12 @@ namespace Gala // precalculate all slot centers Point[] slot_centers = {}; 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++) { 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 var tmplist = clones.copy (); // use a QLinkedList copy instead? @@ -236,15 +238,17 @@ namespace Gala var direction = 0; var directions = new List (); var rects = new List (); + 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] var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); rects.append ({rect.x, rect.y, rect.width, rect.height}); + 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. directions.append (direction); - direction ++; + direction++; if (direction == 4) { direction = 0; } @@ -256,88 +260,88 @@ namespace Gala overlap = false; for (var i = 0; i < rects.length (); i++) { 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))) { - loop_counter ++; - overlap = true; - - // Determine pushing direction - Point i_center = rect_center (rects.nth_data (i)); - Point j_center = rect_center (rects.nth_data (j)); - Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; - - // Prevent dividing by zero and non-movement - if (diff.x == 0 && diff.y == 0) - diff.x = 1; - // Try to keep screen/workspace aspect ratio - if (bounds.height / bounds.width > area.height / area.width) - diff.x *= 2; - else - diff.y *= 2; - - // Approximate a vector of between 10px and 20px in magnitude in the same direction - var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y); - diff.x = (int)Math.floorf (diff.x * ACCURACY / length); - diff.y = (int)Math.floorf (diff.y * ACCURACY / length); - - // Move both windows apart - rects.nth_data (i).x += -diff.x; - rects.nth_data (i).y += -diff.y; - rects.nth_data (j).x += diff.x; - rects.nth_data (j).y += diff.y; - - if (use_more_screen) { - // Try to keep the bounding rect the same aspect as the screen so that more - // 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 - // window towards the outer corner. If it is in any of the other edge sections - // alternate between each corner on that edge. We don't want to determine it - // randomly as it will not produce consistant locations when using the filter. - // Only move one window so we don't cause large amounts of unnecessary zooming - // in some situations. We need to do this even when expanding later just in case - // all windows are the same size. - // (We are using an old bounding rect for this, hopefully it doesn't matter) - var x_section = Math.roundf ((rects.nth_data (i).x - bounds.x) / (bounds.width / 3.0f)); - var y_section = Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); - - i_center = rect_center (rects.nth_data (i)); - diff.x = 0; - diff.y = 0; - if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well - if (x_section == 1) - x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); - if (y_section == 1) - y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); - } - 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); - 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)); + + var rect = rects.nth_data (i); + var comp = rects.nth_data (j); + + if (i == j || rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( + rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS))) + continue; + + loop_counter ++; + overlap = true; + + // Determine pushing direction + Point i_center = rect_center (rect); + Point j_center = rect_center (comp); + Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; + + // Prevent dividing by zero and non-movement + if (diff.x == 0 && diff.y == 0) + diff.x = 1; + // Try to keep screen/workspace aspect ratio + if (bounds.height / bounds.width > area.height / area.width) + diff.x *= 2; + else + diff.y *= 2; + + // Approximate a vector of between 10px and 20px in magnitude in the same direction + var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y); + diff.x = (int)Math.floorf (diff.x * ACCURACY / length); + diff.y = (int)Math.floorf (diff.y * ACCURACY / length); + // Move both windows apart + rect = rect_translate (rect, -diff.x, -diff.y); + comp = rect_translate (comp, diff.x, diff.y); + + // Try to keep the bounding rect the same aspect as the screen so that more + // 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 + // window towards the outer corner. If it is in any of the other edge sections + // alternate between each corner on that edge. We don't want to determine it + // randomly as it will not produce consistant locations when using the filter. + // Only move one window so we don't cause large amounts of unnecessary zooming + // in some situations. We need to do this even when expanding later just in case + // all windows are the same size. + // (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)); + var y_section = (int)Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); + + i_center = rect_center (rect); + diff.x = 0; + diff.y = 0; + if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well + if (x_section == 1) + x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); + if (y_section == 1) + y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); } + 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); @@ -352,16 +356,17 @@ namespace Gala bounds.height = (int)Math.floorf (area.height / scale); // Move all windows back onto the screen and set their scale - for (var i = 0; i < rects.length (); i++) { - rects.nth_data (i).x += -bounds.x; - rects.nth_data (i).y += -bounds.y; + var index = 0; + foreach (var rect in rects) { + rect = rect_translate (rect, -bounds.x, -bounds.y); - rects.nth_data (i).x = (int)Math.floorf (rects.nth_data (i).x * scale + area.x); - rects.nth_data (i).y = (int)Math.floorf (rects.nth_data (i).y * scale + area.y); - rects.nth_data (i).width = (int)Math.floorf (rects.nth_data (i).width * scale); - rects.nth_data (i).height = (int)Math.floorf (rects.nth_data (i).height * scale); + rect = {(int)Math.floorf (rect.x * scale + area.x), + (int)Math.floorf (rect.y * scale + area.y), + (int)Math.floorf (rect.width * 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 (); - 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 ()) { if (window.window_type != WindowType.NORMAL && window.window_type != WindowType.DOCK) { (window.get_compositor_private () as Actor).hide (); @@ -397,6 +399,9 @@ namespace Gala if (n_windows == 0) return; + Compositor.get_background_actor_for_screen (screen). + animate (AnimationMode.EASE_OUT_QUAD, 1000, dim_factor : 0.4); + // sort windows by stacking order var windows = screen.get_display ().sort_windows_by_stacking (used_windows); @@ -426,6 +431,7 @@ namespace Gala calculate_places (get_children ()); } + //called when a window has been closed void reposition (ExposedWindow removed) { var children = get_children ().copy (); From 1fd76ba1416bfa691831f2af93ccc6831b80519b Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 01:28:11 +0200 Subject: [PATCH 30/46] Replace Expo with WindowOverview --- CMakeLists.txt | 2 +- data/org.pantheon.desktop.gala.gschema.xml | 2 +- src/Plugin.vala | 14 +++++++------- src/{Expo.vala => WindowOverview.vala} | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename src/{Expo.vala => WindowOverview.vala} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 493ec47f..1e397931 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ ensure_vala_version("0.16.0" MINIMUM) include(ValaPrecompile) vala_precompile(VALA_C src/DBus.vala - src/Expo.vala + src/WindowOverview.vala src/Main.vala src/Plugin.vala src/Settings.vala diff --git a/data/org.pantheon.desktop.gala.gschema.xml b/data/org.pantheon.desktop.gala.gschema.xml index 705276a4..77b917f1 100644 --- a/data/org.pantheon.desktop.gala.gschema.xml +++ b/data/org.pantheon.desktop.gala.gschema.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Plugin.vala b/src/Plugin.vala index d35f96ff..0900b995 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -27,7 +27,7 @@ namespace Gala MINIMIZE_CURRENT, OPEN_LAUNCHER, CUSTOM_COMMAND, - EXPOSE + WINDOW_OVERVIEW } public enum InputArea { @@ -40,7 +40,7 @@ namespace Gala { WindowSwitcher winswitcher; WorkspaceView workspace_view; - Expo expo; + WindowOverview window_overview; Window? moving; //place for the window that is being moved over @@ -79,16 +79,16 @@ namespace Gala winswitcher = new WindowSwitcher (this); - expo = new Expo (this); + window_overview = new WindowOverview (this); stage.add_child (workspace_view); stage.add_child (winswitcher); - stage.add_child (expo); + stage.add_child (window_overview); /*keybindings*/ screen.get_display ().add_keybinding ("expose-windows", BehaviorSettings.get_default ().schema, 0, () => { - expo.open (true); + window_overview.open (true); }); screen.get_display ().add_keybinding ("move-to-workspace-first", BehaviorSettings.get_default ().schema, 0, () => { screen.get_workspace_by_index (0).activate (screen.get_display ().get_current_time ()); @@ -288,8 +288,8 @@ namespace Gala warning (e.message); } break; - case ActionType.EXPOSE: - expo.open (true); + case ActionType.WINDOW_OVERVIEW: + window_overview.open (true); break; default: warning ("Trying to run unknown action"); diff --git a/src/Expo.vala b/src/WindowOverview.vala similarity index 99% rename from src/Expo.vala rename to src/WindowOverview.vala index 91f30bc1..c82b4637 100644 --- a/src/Expo.vala +++ b/src/WindowOverview.vala @@ -27,7 +27,7 @@ namespace Gala NATURAL } - public class Expo : Actor + public class WindowOverview : Actor { Plugin plugin; Screen screen; @@ -36,7 +36,7 @@ namespace Gala static const int PADDING = 50; - public Expo (Plugin _plugin) + public WindowOverview (Plugin _plugin) { plugin = _plugin; screen = plugin.get_screen (); From bf79a9608bccbbb13fac0567e8fb3934c4274b49 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 01:41:17 +0200 Subject: [PATCH 31/46] Fix problem with natural algo after cleanup --- src/WindowOverview.vala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/WindowOverview.vala b/src/WindowOverview.vala index c82b4637..23353b9f 100644 --- a/src/WindowOverview.vala +++ b/src/WindowOverview.vala @@ -264,7 +264,7 @@ namespace Gala var rect = rects.nth_data (i); var comp = rects.nth_data (j); - if (i == j || rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( + if (i == j || !rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS))) continue; @@ -342,6 +342,10 @@ namespace Gala // Update bounding rect bounds = bounds.union(rect); bounds = bounds.union(comp); + + //we took copies from the rects from our list so we need to reassign them + rects.nth (i).data = rect; + rects.nth (j).data = comp; } } } while (overlap && loop_counter < MAX_TRANSLATIONS); From 514a349a4cff93fef062ddae98a2c9505a5e68d7 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 02:02:26 +0200 Subject: [PATCH 32/46] Cleanup grid_placement --- src/WindowOverview.vala | 83 ++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/src/WindowOverview.vala b/src/WindowOverview.vala index 23353b9f..ae7acecf 100644 --- a/src/WindowOverview.vala +++ b/src/WindowOverview.vala @@ -151,6 +151,7 @@ namespace Gala // Assign slots int slot_width = area.width / columns; int slot_height = area.height / rows; + ExposedWindow[] taken_slots = {}; taken_slots.resize (rows * columns); @@ -159,25 +160,31 @@ namespace Gala 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}; + 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 - var tmplist = clones.copy (); // use a QLinkedList copy instead? + var tmplist = clones.copy (); while (tmplist.length () > 0) { - var w = tmplist.nth_data (0) as ExposedWindow; - var r = w.window.get_outer_rect (); - int slot_candidate = -1; - int slot_candidate_distance = int.MAX; - var pos = rect_center (r); - for (int i = 0; i < columns * rows; i++) { // all slots - int dist = (int)point_distance (pos, slot_centers[i]); - if (dist < slot_candidate_distance) { // window is interested in this slot + var window = tmplist.nth_data (0) as ExposedWindow; + var rect = window.window.get_outer_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++) { + var dist = (int)point_distance (pos, slot_centers[i]); + + if (dist < slot_candidate_distance) { + // window is interested in this slot ExposedWindow occupier = taken_slots[i]; - if (occupier == w) + if (occupier == window) continue; + if (occupier == null || dist < point_distance(rect_center (occupier.window.get_outer_rect ()), slot_centers[i])) { // either nobody lives here, or we're better - takeover the slot if it's our best slot_candidate = i; @@ -185,49 +192,55 @@ namespace Gala } } } + if (slot_candidate == -1) continue; if (taken_slots[slot_candidate] != null) - tmplist.prepend (taken_slots[slot_candidate]); // occupier needs a new home now :p - tmplist.remove_all(w); - taken_slots[slot_candidate] = w; // ...and we rumble in =) + tmplist.prepend (taken_slots[slot_candidate]); + + tmplist.remove_all (window); + taken_slots[slot_candidate] = window; } for (int slot = 0; slot < columns * rows; slot++) { - ExposedWindow w = taken_slots[slot]; - if (w == null) // some slots might be empty + var window = taken_slots[slot]; + // some slots might be empty + if (window == null) continue; - var r = w.window.get_outer_rect (); + + var rect = window.window.get_outer_rect (); // Work out where the slot is Meta.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); // Borders + area.y + (slot / columns) * slot_height, + slot_width, + slot_height}; + target = rect_adjusted (target, 10, 10, -10, -10); + float scale; - if (target.width / (double)r.width < target.height / (double)r.height) { + if (target.width / (double)rect.width < target.height / (double)rect.height) { // Center vertically - scale = target.width / (float)r.width; - target = rect_translate (target, 0, (target.y + (target.height - (int)(r.height * scale)) / 2) - target.y); - target.height = (int)Math.floorf (r.height * scale); + scale = target.width / (float)rect.width; + target = rect_translate (target, 0, (target.y + (target.height - (int)(rect.height * scale)) / 2) - target.y); + target.height = (int)Math.floorf (rect.height * scale); } else { // Center horizontally - scale = target.height / (float)w.height; - target = rect_translate (target, (target.x + (target.width - (int)(r.width * scale)) / 2) - target.x, 0); - target.width = (int)Math.floorf (r.width * scale); + scale = target.height / (float)window.height; + target = rect_translate (target, (target.x + (target.width - (int)(rect.width * scale)) / 2) - target.x, 0); + target.width = (int)Math.floorf (rect.width * scale); } // Don't scale the windows too much - if (scale > 2.0 || (scale > 1.0 && (r.width > 300 || r.height > 300))) { - scale = (r.width > 300 || r.height > 300) ? 1.0f : 2.0f; - target = {rect_center (target).x - (int)Math.floorf (r.width * scale) / 2, - rect_center (target).y - (int)Math.floorf (r.height * scale) / 2, - (int)Math.floorf (scale * r.width), - (int)Math.floorf (scale * r.height)}; + if (scale > 2.0 || (scale > 1.0 && (rect.width > 300 || rect.height > 300))) { + scale = (rect.width > 300 || rect.height > 300) ? 1.0f : 2.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)}; } - place_window (w, target); + place_window (window, target); } } From 63da9e26df9107b6046088e45b6f9666b28b455d Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 02:10:31 +0200 Subject: [PATCH 33/46] Move code to better places, math related stuff to Utils namespace, some minor changes --- src/Utils.vala | 31 +++++++++++++++ src/Widgets/ExposedWindow.vala | 2 +- src/WindowOverview.vala | 69 ++++++++++++---------------------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/Utils.vala b/src/Utils.vala index 0b088d95..c200b540 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -169,4 +169,35 @@ namespace Gala.Utils return fallback_style; } + + /* some math stuff */ + + public struct Point + { + int x; + int y; + } + + public Point rect_center (Meta.Rectangle rect) + { + return {rect.x + rect.width / 2, rect.y + rect.height / 2}; + } + + public Meta.Rectangle rect_adjusted (Meta.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)}; + } + + public Meta.Rectangle rect_translate (Meta.Rectangle rect, int x, int y) + { + return {rect.x + x, rect.y + y, rect.width, rect.height}; + } + + public float point_distance (Point a, Point b) + { + var k1 = b.x - a.x; + var k2 = b.y - a.y; + + return k1*k1 + k2*k2; + } } diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index b61e2ab5..3ccc6a73 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -117,7 +117,7 @@ namespace Gala if (event.related == close_button) return false; - close_button.animate (AnimationMode.EASE_IN_QUAD, 400, scale_x : 0.0f, scale_y : 0.0f) + close_button.animate (AnimationMode.EASE_IN_QUAD, 200, scale_x : 0.0f, scale_y : 0.0f) .completed.connect (() => close_button.visible = false ); return true; diff --git a/src/WindowOverview.vala b/src/WindowOverview.vala index ae7acecf..3d39802f 100644 --- a/src/WindowOverview.vala +++ b/src/WindowOverview.vala @@ -17,6 +17,7 @@ using Meta; using Clutter; +using Gala.Utils; namespace Gala { @@ -49,7 +50,8 @@ namespace Gala public override bool key_press_event (Clutter.KeyEvent event) { - //FIXME need to figure out the actual keycombo, for now leave it by default and others will close it by selecting a window! + //FIXME need to figure out the actual keycombo, for now leave it by + // default and others will close it by selecting a window! if (event.keyval == Clutter.Key.e || event.keyval == Clutter.Key.Escape) { close (true); @@ -69,38 +71,14 @@ namespace Gala * https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp * **/ + + //constants, mainly for natural expo const int GAPS = 20; const int MAX_TRANSLATIONS = 100000; const int ACCURACY = 1; const int BORDER = 10; const int TOP_GAP = 20; - struct Point - { - int x; - int y; - } - - Point rect_center (Meta.Rectangle rect) - { - return {rect.x + rect.width / 2, rect.y + rect.height / 2}; - } - Meta.Rectangle rect_adjusted (Meta.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)}; - } - Meta.Rectangle rect_translate (Meta.Rectangle rect, int x, int y) - { - return {rect.x + x, rect.y + y, rect.width, rect.height}; - } - float point_distance (Point a, Point b) - { - var k1 = b.x - a.x; - var k2 = b.y - a.y; - - return k1*k1 + k2*k2; - } - void calculate_places (List windows) { var clones = windows.copy (); @@ -125,24 +103,6 @@ namespace Gala natural_placement (area, clones); } - public void place_window (ExposedWindow clone, Meta.Rectangle rect) - { - var fscale = rect.width / clone.width; - - //animate the windows and icons to the calculated positions - clone.icon.x = rect.x + Math.floorf (clone.width * fscale / 2.0f - clone.icon.width / 2.0f); - clone.icon.y = rect.y + Math.floorf (clone.height * fscale - 50.0f); - clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); - - clone.close_button.x = rect.x - 10; - clone.close_button.y = rect.y - 10; - - clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:fscale, scale_y:fscale, x:rect.x+0.0f, y:rect.y+0.0f) - .completed.connect (() => ready = true ); - clone.icon.opacity = 0; - clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); - } - void grid_placement (Meta.Rectangle area, List clones) { int columns = (int)Math.ceil (Math.sqrt (clones.length ())); @@ -387,6 +347,25 @@ namespace Gala } } + // animate a window to the given position + void place_window (ExposedWindow clone, Meta.Rectangle rect) + { + var fscale = rect.width / clone.width; + + //animate the windows and icons to the calculated positions + clone.icon.x = rect.x + Math.floorf (clone.width * fscale / 2.0f - clone.icon.width / 2.0f); + clone.icon.y = rect.y + Math.floorf (clone.height * fscale - 50.0f); + clone.icon.get_parent ().set_child_above_sibling (clone.icon, null); + + clone.close_button.x = rect.x - 10; + clone.close_button.y = rect.y - 10; + + clone.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 250, scale_x:fscale, scale_y:fscale, x:rect.x+0.0f, y:rect.y+0.0f) + .completed.connect (() => ready = true ); + clone.icon.opacity = 0; + clone.icon.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 350, scale_x:1.0f, scale_y:1.0f, opacity:255); + } + public void open (bool animate = true) { if (!ready) From f8ddd6eb36582480ab08a6bf1d7ab66b4980ebc8 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 02:46:10 +0200 Subject: [PATCH 34/46] Sort windows by monitor --- src/WindowOverview.vala | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/WindowOverview.vala b/src/WindowOverview.vala index 3d39802f..b947d9cc 100644 --- a/src/WindowOverview.vala +++ b/src/WindowOverview.vala @@ -87,20 +87,32 @@ namespace Gala (int)(b as ExposedWindow).window.get_stable_sequence (); }); - // get the area used by the expo algorithms together - var geom = screen.get_monitor_geometry (screen.get_primary_monitor ()); - var ratio = geom.width / (float)geom.height; - var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); - var y_gap = Math.fmaxf (BORDER / ratio, TOP_GAP); - Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), - (int)Math.floorf (geom.y + TOP_GAP + y_gap), - (int)Math.floorf (geom.width - x_gap), - (int)Math.floorf (geom.height - 100 - y_gap)}; + //sort windows by monitor + List[] monitors = {}; + monitors.resize (screen.get_n_monitors ()); - if (BehaviorSettings.get_default ().schema.get_enum ("window-overview-type") == WindowOverviewType.GRID) - grid_placement (area, clones); - else - natural_placement (area, clones); + foreach (var clone in clones) + monitors[(clone as ExposedWindow).window.get_monitor ()].append (clone); + + for (var i = 0; i < screen.get_n_monitors (); i++) { + if (monitors[i].length () == 0) + continue; + + // get the area used by the expo algorithms together + var geom = screen.get_monitor_geometry (i); + var ratio = geom.width / (float)geom.height; + var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); + var y_gap = Math.fmaxf (BORDER / ratio, TOP_GAP); + Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), + (int)Math.floorf (geom.y + TOP_GAP + y_gap), + (int)Math.floorf (geom.width - x_gap), + (int)Math.floorf (geom.height - 100 - y_gap)}; + + if (BehaviorSettings.get_default ().schema.get_enum ("window-overview-type") == WindowOverviewType.GRID) + grid_placement (area, monitors[i]); + else + natural_placement (area, monitors[i]); + } } void grid_placement (Meta.Rectangle area, List clones) From 60de90e4c8258ca23662839e48e7680a165ce179 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sat, 25 Aug 2012 09:31:15 +0200 Subject: [PATCH 35/46] Some minor fixes --- CMakeLists.txt | 2 +- src/Utils.vala | 2 +- src/{ => Widgets}/WindowOverview.vala | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) rename src/{ => Widgets}/WindowOverview.vala (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e397931..9da6749a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,6 @@ ensure_vala_version("0.16.0" MINIMUM) include(ValaPrecompile) vala_precompile(VALA_C src/DBus.vala - src/WindowOverview.vala src/Main.vala src/Plugin.vala src/Settings.vala @@ -56,6 +55,7 @@ vala_precompile(VALA_C src/Utils.vala src/Widgets/AppIcon.vala src/Widgets/ExposedWindow.vala + src/Widgets/WindowOverview.vala src/Widgets/WindowSwitcher.vala src/Widgets/WorkspaceThumb.vala src/Widgets/WorkspaceView.vala diff --git a/src/Utils.vala b/src/Utils.vala index c200b540..1080bdae 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -193,7 +193,7 @@ namespace Gala.Utils return {rect.x + x, rect.y + y, rect.width, rect.height}; } - public float point_distance (Point a, Point b) + public int squared_distance (Point a, Point b) { var k1 = b.x - a.x; var k2 = b.y - a.y; diff --git a/src/WindowOverview.vala b/src/Widgets/WindowOverview.vala similarity index 96% rename from src/WindowOverview.vala rename to src/Widgets/WindowOverview.vala index b947d9cc..3150b022 100644 --- a/src/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -128,7 +128,7 @@ namespace Gala taken_slots.resize (rows * columns); // precalculate all slot centers - Point[] slot_centers = {}; + Utils.Point[] slot_centers = {}; slot_centers.resize (rows * columns); for (int x = 0; x < columns; x++) { for (int y = 0; y < rows; y++) { @@ -149,7 +149,7 @@ namespace Gala // all slots for (int i = 0; i < columns * rows; i++) { - var dist = (int)point_distance (pos, slot_centers[i]); + var dist = squared_distance (pos, slot_centers[i]); if (dist < slot_candidate_distance) { // window is interested in this slot @@ -157,7 +157,7 @@ namespace Gala if (occupier == window) continue; - if (occupier == null || dist < point_distance(rect_center (occupier.window.get_outer_rect ()), slot_centers[i])) { + if (occupier == null || dist < squared_distance (rect_center (occupier.window.get_outer_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; @@ -257,9 +257,9 @@ namespace Gala overlap = true; // Determine pushing direction - Point i_center = rect_center (rect); - Point j_center = rect_center (comp); - Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; + Utils.Point i_center = rect_center (rect); + Utils.Point j_center = rect_center (comp); + Utils.Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; // Prevent dividing by zero and non-movement if (diff.x == 0 && diff.y == 0) @@ -288,8 +288,8 @@ namespace Gala // in some situations. We need to do this even when expanding later just in case // all windows are the same size. // (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)); - var y_section = (int)Math.roundf ((rects.nth_data (j).y - bounds.y) / (bounds.height / 3.0f)); + var x_section = (int)Math.roundf ((rect.x - bounds.x) / (bounds.width / 3.0f)); + var y_section = (int)Math.roundf ((comp.y - bounds.y) / (bounds.height / 3.0f)); i_center = rect_center (rect); diff.x = 0; From 5d1c6e9a4febbe9a47b28871d0621e19541a4695 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sat, 25 Aug 2012 11:51:33 +0200 Subject: [PATCH 36/46] Remove some useless methods --- src/Utils.vala | 15 ++------------- src/Widgets/WindowOverview.vala | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/Utils.vala b/src/Utils.vala index 1080bdae..dd3668a1 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -172,13 +172,7 @@ namespace Gala.Utils /* some math stuff */ - public struct Point - { - int x; - int y; - } - - public Point rect_center (Meta.Rectangle rect) + public Gdk.Point rect_center (Meta.Rectangle rect) { return {rect.x + rect.width / 2, rect.y + rect.height / 2}; } @@ -188,12 +182,7 @@ namespace Gala.Utils return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)}; } - public Meta.Rectangle rect_translate (Meta.Rectangle rect, int x, int y) - { - return {rect.x + x, rect.y + y, rect.width, rect.height}; - } - - public int squared_distance (Point a, Point b) + public int squared_distance (Gdk.Point a, Gdk.Point b) { var k1 = b.x - a.x; var k2 = b.y - a.y; diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 3150b022..556cdc01 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -128,7 +128,7 @@ namespace Gala taken_slots.resize (rows * columns); // precalculate all slot centers - Utils.Point[] 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++) { @@ -194,12 +194,12 @@ namespace Gala if (target.width / (double)rect.width < target.height / (double)rect.height) { // Center vertically scale = target.width / (float)rect.width; - target = rect_translate (target, 0, (target.y + (target.height - (int)(rect.height * scale)) / 2) - target.y); + target.y += (target.height - (int)(rect.height * scale)) / 2; target.height = (int)Math.floorf (rect.height * scale); } else { // Center horizontally scale = target.height / (float)window.height; - target = rect_translate (target, (target.x + (target.width - (int)(rect.width * scale)) / 2) - target.x, 0); + target.x += (target.width - (int)(rect.width * scale)) / 2; target.width = (int)Math.floorf (rect.width * scale); } @@ -257,9 +257,9 @@ namespace Gala overlap = true; // Determine pushing direction - Utils.Point i_center = rect_center (rect); - Utils.Point j_center = rect_center (comp); - Utils.Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; + Gdk.Point i_center = rect_center (rect); + Gdk.Point j_center = rect_center (comp); + Gdk.Point diff = {j_center.x - i_center.x, j_center.y - i_center.y}; // Prevent dividing by zero and non-movement if (diff.x == 0 && diff.y == 0) @@ -275,8 +275,10 @@ namespace Gala diff.x = (int)Math.floorf (diff.x * ACCURACY / length); diff.y = (int)Math.floorf (diff.y * ACCURACY / length); // Move both windows apart - rect = rect_translate (rect, -diff.x, -diff.y); - comp = rect_translate (comp, diff.x, diff.y); + rect.x += -diff.x; + rect.y += -diff.y; + comp.x += diff.x; + comp.y += diff.y; // Try to keep the bounding rect the same aspect as the screen so that more // screen real estate is utilised. We do this by splitting the screen into nine @@ -347,10 +349,8 @@ namespace Gala // Move all windows back onto the screen and set their scale var index = 0; foreach (var rect in rects) { - rect = rect_translate (rect, -bounds.x, -bounds.y); - - rect = {(int)Math.floorf (rect.x * scale + area.x), - (int)Math.floorf (rect.y * scale + area.y), + rect = {(int)Math.floorf ((rect.x - bounds.x) * scale + area.x), + (int)Math.floorf ((rect.y - bounds.y) * scale + area.y), (int)Math.floorf (rect.width * scale), (int)Math.floorf (rect.height * scale)}; From 641c51094ddb9886e73cc3a44941275b054f12f4 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sat, 25 Aug 2012 12:56:32 +0200 Subject: [PATCH 37/46] Use arrays instead of lists in natural-placement --- src/Widgets/WindowOverview.vala | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 556cdc01..b614ee6d 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -67,9 +67,8 @@ namespace Gala } /** - * Code taken from KWin present windows effect + * Code ported from KWin present windows effect * https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp - * **/ //constants, mainly for natural expo @@ -221,36 +220,36 @@ namespace Gala Meta.Rectangle bounds = {area.x, area.y, area.width, area.height}; var direction = 0; - var directions = new List (); - var rects = new List (); + int[] directions = new int[clones.length ()]; + Meta.Rectangle[] rects = new Meta.Rectangle[clones.length ()]; - for (var i = 0; i < clones.length (); i++) { + for (int 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] var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); - rects.append ({rect.x, rect.y, rect.width, rect.height}); - - bounds = bounds.union (rects.nth_data (i)); + rects[i] = rect; + bounds = bounds.union (rect); // 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[i] = direction; direction++; - if (direction == 4) { + if (direction == 4) direction = 0; - } } var loop_counter = 0; var overlap = false; do { overlap = false; - for (var i = 0; i < rects.length (); i++) { - for (var j = 0; j < rects.length (); j++) { + for (var i = 0; i < rects.length; i++) { + for (var j = 0; j < rects.length; j++) { + if (i == j) + continue; - var rect = rects.nth_data (i); - var comp = rects.nth_data (j); + var rect = rects[i]; + var comp = rects[j]; - if (i == j || !rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( - rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS))) + if (!rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( + rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS))) continue; loop_counter ++; @@ -298,9 +297,9 @@ namespace Gala diff.y = 0; if (x_section != 1 || y_section != 1) { // Remove this if you want the center to pull as well if (x_section == 1) - x_section = (directions.nth_data (i) / 2 == 1 ? 2 : 0); + x_section = (directions[i] / 2 == 1 ? 2 : 0); if (y_section == 1) - y_section = (directions.nth_data (i) % 2 == 1 ? 2 : 0); + y_section = (directions[i] % 2 == 1 ? 2 : 0); } if (x_section == 0 && y_section == 0) { diff.x = bounds.x - i_center.x; @@ -331,8 +330,8 @@ namespace Gala bounds = bounds.union(comp); //we took copies from the rects from our list so we need to reassign them - rects.nth (i).data = rect; - rects.nth (j).data = comp; + rects[i] = rect; + rects[j] = comp; } } } while (overlap && loop_counter < MAX_TRANSLATIONS); From 990d51bfa994e58b408ec4f4d903016796bee23b Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 15:13:44 +0200 Subject: [PATCH 38/46] Port the enlarging part for the natural placement algorithm --- src/Utils.vala | 20 +++++++++ src/Widgets/WindowOverview.vala | 74 ++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/Utils.vala b/src/Utils.vala index dd3668a1..f53fc108 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -182,6 +182,21 @@ namespace Gala.Utils return {rect.x + dx1, rect.y + dy1, rect.width + (-dx1 + dx2), rect.height + (-dy1 + dy2)}; } + public bool rect_is_overlapping_any (Meta.Rectangle rect, Meta.Rectangle[] rects, Meta.Rectangle border) + { + if (!border.contains_rect (rect)) + return true; + foreach (var comp in rects) { + if (comp == rect) + continue; + + if (rect_adjusted (rect, -5, -5, 5, 5).overlap (rect_adjusted (comp, -5, -5, 5, 5))) + return true; + } + + return false; + } + public int squared_distance (Gdk.Point a, Gdk.Point b) { var k1 = b.x - a.x; @@ -189,4 +204,9 @@ namespace Gala.Utils return k1*k1 + k2*k2; } + + public int height_for_width (Meta.Rectangle rect, int width) + { + return (int)Math.floorf ((width / (float)rect.width) * rect.height); + } } diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index b614ee6d..1c1b8276 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -74,7 +74,7 @@ namespace Gala //constants, mainly for natural expo const int GAPS = 20; const int MAX_TRANSLATIONS = 100000; - const int ACCURACY = 1; + const int ACCURACY = 20; const int BORDER = 10; const int TOP_GAP = 20; @@ -353,7 +353,77 @@ namespace Gala (int)Math.floorf (rect.width * scale), (int)Math.floorf (rect.height * scale)}; - place_window (clones.nth_data (index) as ExposedWindow, rect); + rects[index] = rect; + index++; + } + + // fill gaps by enlarging windows + bool moved = false; + Meta.Rectangle border = area; + do { + moved = false; + + index = 0; + foreach (var rect in rects) { + + int width_diff = ACCURACY; + int height_diff = height_for_width (rect, (rect.width + width_diff) - rect.height); + int x_diff = width_diff / 2; + int y_diff = height_diff / 2; + + //top right + Meta.Rectangle old = {rect.x, rect.y, rect.width, rect.height}; + rect = {rect.x + x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff}; + if (rect_is_overlapping_any (rect, rects, border)) + rect = old; + else + moved = true; + + //bottom right + old = {rect.x, rect.y, rect.width, rect.height}; + rect = {rect.x + x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff}; + if (rect_is_overlapping_any (rect, rects, border)) + rect = old; + else + moved = true; + + //bottom left + old = {rect.x, rect.y, rect.width, rect.height}; + rect = {rect.x - x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff}; + if (rect_is_overlapping_any (rect, rects, border)) + rect = old; + else + moved = true; + + //top left + old = {rect.x, rect.y, rect.width, rect.height}; + rect = {rect.x - x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff}; + if (rect_is_overlapping_any (rect, rects, border)) + rect = old; + else + moved = true; + + rects[index] = rect; + index++; + } + } while (moved); + + index = 0; + foreach (var rect in rects) { + var window = clones.nth_data (index) as ExposedWindow; + var window_rect = window.window.get_outer_rect (); + + scale = rect.width / (float)window_rect.width; + + if (scale > 2.0 || (scale > 1.0 && (window_rect.width > 300 || window_rect.height > 300))) { + scale = (window_rect.width > 300 || window_rect.height > 300) ? 1.0f : 2.0f; + rect = {rect_center (rect).x - (int)Math.floorf (window_rect.width * scale) / 2, + rect_center (rect).y - (int)Math.floorf (window_rect.height * scale) / 2, + (int)Math.floorf (window_rect.width * scale), + (int)Math.floorf (window_rect.height * scale)}; + } + + place_window (window, rect); index++; } } From 9504eaa1847cd4cb23669cb82770ae580ce3b457 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sat, 25 Aug 2012 15:32:40 +0200 Subject: [PATCH 39/46] Some more cleanups for natural placement --- src/Utils.vala | 40 ------------------------- src/Widgets/WindowOverview.vala | 52 ++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 51 deletions(-) diff --git a/src/Utils.vala b/src/Utils.vala index f53fc108..0b088d95 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -169,44 +169,4 @@ namespace Gala.Utils return fallback_style; } - - /* some math stuff */ - - public Gdk.Point rect_center (Meta.Rectangle rect) - { - return {rect.x + rect.width / 2, rect.y + rect.height / 2}; - } - - public Meta.Rectangle rect_adjusted (Meta.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)}; - } - - public bool rect_is_overlapping_any (Meta.Rectangle rect, Meta.Rectangle[] rects, Meta.Rectangle border) - { - if (!border.contains_rect (rect)) - return true; - foreach (var comp in rects) { - if (comp == rect) - continue; - - if (rect_adjusted (rect, -5, -5, 5, 5).overlap (rect_adjusted (comp, -5, -5, 5, 5))) - return true; - } - - return false; - } - - public 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; - } - - public int height_for_width (Meta.Rectangle rect, int width) - { - return (int)Math.floorf ((width / (float)rect.width) * rect.height); - } } diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 1c1b8276..80a8f389 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -17,7 +17,6 @@ using Meta; using Clutter; -using Gala.Utils; namespace Gala { @@ -78,6 +77,41 @@ namespace Gala const int BORDER = 10; const int TOP_GAP = 20; + //some math utilities + 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; + } + + bool rect_is_overlapping_any (Meta.Rectangle rect, Meta.Rectangle[] rects, Meta.Rectangle border) + { + if (!border.contains_rect (rect)) + return true; + foreach (var comp in rects) { + if (comp == rect) + continue; + + if (rect_adjusted (rect, -5, -5, 5, 5).overlap (rect_adjusted (comp, -5, -5, 5, 5))) + return true; + } + + return false; + } + + Meta.Rectangle rect_adjusted (Meta.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)}; + } + + Gdk.Point rect_center (Meta.Rectangle rect) + { + return {rect.x + rect.width / 2, rect.y + rect.height / 2}; + } + + void calculate_places (List windows) { var clones = windows.copy (); @@ -263,11 +297,6 @@ namespace Gala // Prevent dividing by zero and non-movement if (diff.x == 0 && diff.y == 0) diff.x = 1; - // Try to keep screen/workspace aspect ratio - if (bounds.height / bounds.width > area.height / area.width) - diff.x *= 2; - else - diff.y *= 2; // Approximate a vector of between 10px and 20px in magnitude in the same direction var length = Math.sqrtf (diff.x * diff.x + diff.y * diff.y); @@ -367,12 +396,13 @@ namespace Gala foreach (var rect in rects) { int width_diff = ACCURACY; - int height_diff = height_for_width (rect, (rect.width + width_diff) - rect.height); + int height_diff = (int)Math.floorf ((((rect.width + width_diff) - rect.height) / + (float)rect.width) * rect.height); int x_diff = width_diff / 2; int y_diff = height_diff / 2; //top right - Meta.Rectangle old = {rect.x, rect.y, rect.width, rect.height}; + Meta.Rectangle old = rect; rect = {rect.x + x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff}; if (rect_is_overlapping_any (rect, rects, border)) rect = old; @@ -380,7 +410,7 @@ namespace Gala moved = true; //bottom right - old = {rect.x, rect.y, rect.width, rect.height}; + old = rect; rect = {rect.x + x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff}; if (rect_is_overlapping_any (rect, rects, border)) rect = old; @@ -388,7 +418,7 @@ namespace Gala moved = true; //bottom left - old = {rect.x, rect.y, rect.width, rect.height}; + old = rect; rect = {rect.x - x_diff, rect.y + y_diff, rect.width + width_diff, rect.height + width_diff}; if (rect_is_overlapping_any (rect, rects, border)) rect = old; @@ -396,7 +426,7 @@ namespace Gala moved = true; //top left - old = {rect.x, rect.y, rect.width, rect.height}; + old = rect; rect = {rect.x - x_diff, rect.y - y_diff - height_diff, rect.width + width_diff, rect.height + width_diff}; if (rect_is_overlapping_any (rect, rects, border)) rect = old; From 1f5daa907f33d9662736f012853b2280ca88308e Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sat, 25 Aug 2012 16:23:16 +0200 Subject: [PATCH 40/46] Optimize a bit with the cost of behaviour change --- src/Widgets/WindowOverview.vala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 80a8f389..43402160 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -71,7 +71,7 @@ namespace Gala **/ //constants, mainly for natural expo - const int GAPS = 20; + const int GAPS = 10; const int MAX_TRANSLATIONS = 100000; const int ACCURACY = 20; const int BORDER = 10; @@ -94,7 +94,7 @@ namespace Gala if (comp == rect) continue; - if (rect_adjusted (rect, -5, -5, 5, 5).overlap (rect_adjusted (comp, -5, -5, 5, 5))) + if (rect.overlap (comp)) return true; } @@ -260,6 +260,7 @@ namespace Gala for (int 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] var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); + rect = rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS); rects[i] = rect; bounds = bounds.union (rect); @@ -282,8 +283,7 @@ namespace Gala var rect = rects[i]; var comp = rects[j]; - if (!rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS).overlap ( - rect_adjusted (comp, -GAPS, -GAPS, GAPS, GAPS))) + if (!rect.overlap (comp)) continue; loop_counter ++; @@ -443,6 +443,7 @@ namespace Gala var window = clones.nth_data (index) as ExposedWindow; var window_rect = window.window.get_outer_rect (); + rect = rect_adjusted(rect, GAPS, GAPS, -GAPS, -GAPS); scale = rect.width / (float)window_rect.width; if (scale > 2.0 || (scale > 1.0 && (window_rect.width > 300 || window_rect.height > 300))) { From 2a8537ec9108241907cf5b2193e3eb9e88f75b55 Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 26 Aug 2012 16:44:07 +0200 Subject: [PATCH 41/46] Update to newest granite API for get_close_pixbuf --- src/Widgets/WorkspaceThumb.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Widgets/WorkspaceThumb.vala b/src/Widgets/WorkspaceThumb.vala index 4953ea01..5cb9d3df 100644 --- a/src/Widgets/WorkspaceThumb.vala +++ b/src/Widgets/WorkspaceThumb.vala @@ -94,7 +94,7 @@ namespace Gala close_button = new GtkClutter.Texture (); try { - close_button.set_from_pixbuf (Granite.Widgets.get_close_pixbuf ()); + close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ()); } catch (Error e) { warning (e.message); } close_button.x = -12.0f; close_button.y = -10.0f; From c386bae53bce1209bede80ab966c98d8139160dd Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 26 Aug 2012 23:20:57 +0200 Subject: [PATCH 42/46] Simplify area calculation --- src/Widgets/ExposedWindow.vala | 2 +- src/Widgets/WindowOverview.vala | 12 +++++------- src/Widgets/WorkspaceThumb.vala | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/ExposedWindow.vala index 3ccc6a73..4122d7ec 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/ExposedWindow.vala @@ -58,7 +58,7 @@ namespace Gala close_button.leave_event.connect ((e) => leave_event (e)); try { - close_button.set_from_pixbuf (Granite.Widgets.get_close_pixbuf ()); + close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ()); } catch (Error e) { warning (e.message); } add_child (clone); diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 43402160..087597b5 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -76,6 +76,7 @@ namespace Gala const int ACCURACY = 20; const int BORDER = 10; const int TOP_GAP = 20; + const int BOTTOM_GAP = 100; //some math utilities int squared_distance (Gdk.Point a, Gdk.Point b) @@ -133,13 +134,10 @@ namespace Gala // get the area used by the expo algorithms together var geom = screen.get_monitor_geometry (i); - var ratio = geom.width / (float)geom.height; - var x_gap = Math.fmaxf (BORDER, TOP_GAP * ratio); - var y_gap = Math.fmaxf (BORDER / ratio, TOP_GAP); - Meta.Rectangle area = {(int)Math.floorf (geom.x + x_gap / 2), - (int)Math.floorf (geom.y + TOP_GAP + y_gap), - (int)Math.floorf (geom.width - x_gap), - (int)Math.floorf (geom.height - 100 - y_gap)}; + Meta.Rectangle area = {(int)Math.floorf (geom.x + BORDER), + (int)Math.floorf (geom.y + TOP_GAP), + (int)Math.floorf (geom.width - BORDER * 2), + (int)Math.floorf (geom.height - BOTTOM_GAP)}; if (BehaviorSettings.get_default ().schema.get_enum ("window-overview-type") == WindowOverviewType.GRID) grid_placement (area, monitors[i]); diff --git a/src/Widgets/WorkspaceThumb.vala b/src/Widgets/WorkspaceThumb.vala index 4953ea01..5cb9d3df 100644 --- a/src/Widgets/WorkspaceThumb.vala +++ b/src/Widgets/WorkspaceThumb.vala @@ -94,7 +94,7 @@ namespace Gala close_button = new GtkClutter.Texture (); try { - close_button.set_from_pixbuf (Granite.Widgets.get_close_pixbuf ()); + close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ()); } catch (Error e) { warning (e.message); } close_button.x = -12.0f; close_button.y = -10.0f; From 9703085e4fefd978c3aa207dc7583498131d0f9d Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Sun, 26 Aug 2012 23:26:06 +0200 Subject: [PATCH 43/46] Rename ExposedWindow to WindowThumb --- CMakeLists.txt | 2 +- src/Widgets/WindowOverview.vala | 24 +++++++++---------- .../{ExposedWindow.vala => WindowThumb.vala} | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) rename src/Widgets/{ExposedWindow.vala => WindowThumb.vala} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9da6749a..86c2088d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,9 +54,9 @@ vala_precompile(VALA_C src/TextShadowEffect.vala src/Utils.vala src/Widgets/AppIcon.vala - src/Widgets/ExposedWindow.vala src/Widgets/WindowOverview.vala src/Widgets/WindowSwitcher.vala + src/Widgets/WindowThumb.vala src/Widgets/WorkspaceThumb.vala src/Widgets/WorkspaceView.vala ${CMAKE_BINARY_DIR}/src/Config.vala diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 087597b5..0cb4f860 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -117,8 +117,8 @@ namespace Gala { var clones = windows.copy (); 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 WindowThumb).window.get_stable_sequence () - + (int)(b as WindowThumb).window.get_stable_sequence (); }); //sort windows by monitor @@ -126,7 +126,7 @@ namespace Gala monitors.resize (screen.get_n_monitors ()); foreach (var clone in clones) - monitors[(clone as ExposedWindow).window.get_monitor ()].append (clone); + monitors[(clone as WindowThumb).window.get_monitor ()].append (clone); for (var i = 0; i < screen.get_n_monitors (); i++) { if (monitors[i].length () == 0) @@ -155,7 +155,7 @@ namespace Gala int slot_width = area.width / columns; int slot_height = area.height / rows; - ExposedWindow[] taken_slots = {}; + WindowThumb[] taken_slots = {}; taken_slots.resize (rows * columns); // precalculate all slot centers @@ -171,7 +171,7 @@ namespace Gala // Assign each window to the closest available slot var tmplist = clones.copy (); while (tmplist.length () > 0) { - var window = tmplist.nth_data (0) as ExposedWindow; + var window = tmplist.nth_data (0) as WindowThumb; var rect = window.window.get_outer_rect (); var slot_candidate = -1; @@ -184,7 +184,7 @@ namespace Gala if (dist < slot_candidate_distance) { // window is interested in this slot - ExposedWindow occupier = taken_slots[i]; + WindowThumb occupier = taken_slots[i]; if (occupier == window) continue; @@ -257,7 +257,7 @@ namespace Gala for (int 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] - var rect = (clones.nth_data (i) as ExposedWindow).window.get_outer_rect (); + var rect = (clones.nth_data (i) as WindowThumb).window.get_outer_rect (); rect = rect_adjusted(rect, -GAPS, -GAPS, GAPS, GAPS); rects[i] = rect; bounds = bounds.union (rect); @@ -438,7 +438,7 @@ namespace Gala index = 0; foreach (var rect in rects) { - var window = clones.nth_data (index) as ExposedWindow; + var window = clones.nth_data (index) as WindowThumb; var window_rect = window.window.get_outer_rect (); rect = rect_adjusted(rect, GAPS, GAPS, -GAPS, -GAPS); @@ -458,7 +458,7 @@ namespace Gala } // animate a window to the given position - void place_window (ExposedWindow clone, Meta.Rectangle rect) + void place_window (WindowThumb clone, Meta.Rectangle rect) { var fscale = rect.width / clone.width; @@ -524,7 +524,7 @@ namespace Gala return; actor.hide (); - var clone = new ExposedWindow (window); + var clone = new WindowThumb (window); clone.x = actor.x; clone.y = actor.y; @@ -538,7 +538,7 @@ namespace Gala } //called when a window has been closed - void reposition (ExposedWindow removed) + void reposition (WindowThumb removed) { var children = get_children ().copy (); children.remove (removed); @@ -563,7 +563,7 @@ namespace Gala plugin.update_input_area (); foreach (var child in get_children ()) { - var exposed = child as ExposedWindow; + var exposed = child as WindowThumb; exposed.close (animate); exposed.selected.disconnect (selected); } diff --git a/src/Widgets/ExposedWindow.vala b/src/Widgets/WindowThumb.vala similarity index 98% rename from src/Widgets/ExposedWindow.vala rename to src/Widgets/WindowThumb.vala index 4122d7ec..2935f812 100644 --- a/src/Widgets/ExposedWindow.vala +++ b/src/Widgets/WindowThumb.vala @@ -20,7 +20,7 @@ using Clutter; namespace Gala { - public class ExposedWindow : Actor + public class WindowThumb : Actor { public weak Window window; Clone clone; @@ -30,7 +30,7 @@ namespace Gala public signal void selected (Window window); public signal void reposition (); - public ExposedWindow (Window _window) + public WindowThumb (Window _window) { window = _window; From 85883f027f2fbd4f146be1e3acf49034e3ea572d Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Mon, 27 Aug 2012 01:22:30 +0200 Subject: [PATCH 44/46] Animate windows back in after alt tabbing --- src/Widgets/WindowSwitcher.vala | 54 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/Widgets/WindowSwitcher.vala b/src/Widgets/WindowSwitcher.vala index 0ca70134..83a5c1a4 100644 --- a/src/Widgets/WindowSwitcher.vala +++ b/src/Widgets/WindowSwitcher.vala @@ -116,36 +116,38 @@ namespace Gala void close (uint time) { - foreach (var clone in window_clones) { - remove_child (clone); - clone.destroy (); - } + var screen = plugin.get_screen (); + var display = screen.get_display (); - Meta.Compositor.get_window_actors (plugin.get_screen ()).foreach ((w) => { - var meta_win = w.get_meta_window (); - if (!meta_win.minimized && - (meta_win.get_workspace () == plugin.get_screen ().get_active_workspace ()) || - meta_win.is_on_all_workspaces ()) - w.show (); - }); if (dock_window != null) dock_window.opacity = 0; - window_clones.clear (); - - plugin.end_modal (); - if (current_window != null) { - current_window.activate (time); - current_window = null; - } - var dest_width = (dock_window != null ? dock_window.width : 800.0f); set_child_above_sibling (dock, null); dock_background.animate (AnimationMode.EASE_OUT_CUBIC, 250, opacity : 0); - if (dock_window != null) + if (dock_window != null) { + dock_window.show (); dock_window.animate (AnimationMode.LINEAR, 250, opacity : 255); + } + + foreach (var clone in window_clones) { + //current window stays on top + if ((clone.source as Meta.WindowActor).get_meta_window () == current_window) + continue; + + //reset order + clone.get_parent ().set_child_below_sibling (clone, null); + clone.animate (AnimationMode.EASE_OUT_CUBIC, 150, depth : 0.0f, opacity : 255); + } + + if (current_window != null) { + current_window.activate (time); + current_window = null; + } + + plugin.end_modal (); dock.animate (AnimationMode.EASE_OUT_CUBIC, 250, width:dest_width, opacity : 0). completed.connect (() => { @@ -155,6 +157,18 @@ namespace Gala dock_window = null; visible = false; + + foreach (var clone in window_clones) + clone.destroy (); + window_clones.clear (); + + Meta.Compositor.get_window_actors (plugin.get_screen ()).foreach ((w) => { + var meta_win = w.get_meta_window (); + if (!meta_win.minimized && + (meta_win.get_workspace () == plugin.get_screen ().get_active_workspace ()) || + meta_win.is_on_all_workspaces ()) + w.show (); + }); }); } From 2199aa2e174c4c0fb2104128502aa9264ac30f81 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Mon, 27 Aug 2012 23:01:09 +0200 Subject: [PATCH 45/46] grid-placement: avoid empty window-slot which would make it look weird --- src/Widgets/WindowOverview.vala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Widgets/WindowOverview.vala b/src/Widgets/WindowOverview.vala index 0cb4f860..5766cf28 100644 --- a/src/Widgets/WindowOverview.vala +++ b/src/Widgets/WindowOverview.vala @@ -170,6 +170,7 @@ namespace Gala // Assign each window to the closest available slot var tmplist = clones.copy (); + var window_count = tmplist.length (); while (tmplist.length () > 0) { var window = tmplist.nth_data (0) as WindowThumb; var rect = window.window.get_outer_rect (); @@ -180,6 +181,9 @@ namespace Gala // 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) { From 293be336422b3007d501daf16a97ca7302fcbd5e Mon Sep 17 00:00:00 2001 From: Tom Beckmann Date: Mon, 27 Aug 2012 23:44:52 +0200 Subject: [PATCH 46/46] Assign color used as background color as the stage's background color --- src/Plugin.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Plugin.vala b/src/Plugin.vala index 3c2fde09..2b5267e3 100644 --- a/src/Plugin.vala +++ b/src/Plugin.vala @@ -69,7 +69,9 @@ namespace Gala DBus.init (this); var stage = Compositor.get_stage_for_screen (screen) as Clutter.Stage; - stage.background_color = {0, 0, 0, 255}; + + string color = new Settings ("org.gnome.desktop.background").get_string ("primary-color"); + stage.background_color = Clutter.Color.from_string (color); stage.no_clear_hint = true; screen.override_workspace_layout (ScreenCorner.TOPLEFT, false, 1, -1);