mirror of
https://github.com/elementary/gala.git
synced 2025-01-08 11:06:59 +03:00
Improves the multitasking view
It fixes the issue when the view was exited while it was animating a workspaceswitch where the windows would "get stuck" mid-animation and jump into place after the animation is finished. It slides out dock windows that are found at the top and bottom of the screen to provide a smoother open experience.
This commit is contained in:
commit
a1eac874a8
@ -55,7 +55,7 @@ namespace Gala
|
||||
#else
|
||||
background = new Background (screen, monitor, BackgroundSettings.get_default ().schema);
|
||||
#endif
|
||||
background.set_easing_duration (300);
|
||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||
|
||||
window_container = new WindowCloneContainer ();
|
||||
window_container.window_selected.connect ((w) => { window_selected (w); });
|
||||
|
@ -27,7 +27,8 @@ namespace Gala
|
||||
*/
|
||||
public class MultitaskingView : Actor, ActivatableComponent
|
||||
{
|
||||
const int HIDING_DURATION = 300;
|
||||
public const int ANIMATION_DURATION = 250;
|
||||
public const AnimationMode ANIMATION_MODE = AnimationMode.EASE_OUT_QUAD;
|
||||
const int SMOOTH_SCROLL_DELAY = 500;
|
||||
|
||||
public WindowManager wm { get; construct; }
|
||||
@ -43,6 +44,7 @@ namespace Gala
|
||||
|
||||
IconGroupContainer icon_groups;
|
||||
Actor workspaces;
|
||||
Actor dock_clones;
|
||||
|
||||
public MultitaskingView (WindowManager wm)
|
||||
{
|
||||
@ -64,8 +66,11 @@ namespace Gala
|
||||
icon_groups = new IconGroupContainer (screen);
|
||||
icon_groups.request_reposition.connect (() => reposition_icon_groups (true));
|
||||
|
||||
dock_clones = new Actor ();
|
||||
|
||||
add_child (icon_groups);
|
||||
add_child (workspaces);
|
||||
add_child (dock_clones);
|
||||
|
||||
foreach (var workspace in screen.get_workspaces ())
|
||||
add_workspace (workspace.index ());
|
||||
@ -226,11 +231,14 @@ namespace Gala
|
||||
workspace_clone.active = false;
|
||||
}
|
||||
|
||||
workspace_clone.save_easing_state ();
|
||||
workspace_clone.set_easing_duration (animate ? 200 : 0);
|
||||
workspace_clone.x = dest_x;
|
||||
workspace_clone.restore_easing_state ();
|
||||
}
|
||||
|
||||
workspaces.set_easing_duration (animate ? 300 : 0);
|
||||
workspaces.set_easing_duration (animate ?
|
||||
AnimationSettings.get_default ().workspace_switch_duration : 0);
|
||||
workspaces.x = -active_x;
|
||||
|
||||
reposition_icon_groups (animate);
|
||||
@ -473,6 +481,11 @@ namespace Gala
|
||||
if (active_workspace != null)
|
||||
workspaces.set_child_above_sibling (active_workspace, null);
|
||||
|
||||
workspaces.remove_all_transitions ();
|
||||
foreach (var child in workspaces.get_children ()) {
|
||||
child.remove_all_transitions ();
|
||||
}
|
||||
|
||||
update_positions (false);
|
||||
|
||||
foreach (var child in workspaces.get_children ()) {
|
||||
@ -483,8 +496,54 @@ namespace Gala
|
||||
workspace.close ();
|
||||
}
|
||||
|
||||
float clone_offset_x, clone_offset_y;
|
||||
dock_clones.get_transformed_position (out clone_offset_x, out clone_offset_y);
|
||||
|
||||
if (opening) {
|
||||
unowned List<WindowActor> actors = Compositor.get_window_actors (screen);
|
||||
|
||||
foreach (var actor in actors) {
|
||||
const int MAX_OFFSET = 100;
|
||||
|
||||
var window = actor.get_meta_window ();
|
||||
|
||||
if (window.window_type != WindowType.DOCK)
|
||||
continue;
|
||||
|
||||
var monitor_geom = screen.get_monitor_geometry (window.get_monitor ());
|
||||
|
||||
#if HAS_MUTTER312
|
||||
var window_geom = window.get_frame_rect ();
|
||||
#else
|
||||
var window_geom = window.get_outer_rect ();
|
||||
#endif
|
||||
var top = monitor_geom.y + MAX_OFFSET > window_geom.y;
|
||||
var bottom = monitor_geom.y + monitor_geom.height - MAX_OFFSET > window_geom.y;
|
||||
|
||||
if (!top && !bottom)
|
||||
continue;
|
||||
|
||||
var clone = new SafeWindowClone (window, true);
|
||||
clone.set_position (actor.x - clone_offset_x, actor.y - clone_offset_y);
|
||||
clone.set_easing_duration (ANIMATION_DURATION);
|
||||
clone.set_easing_mode (ANIMATION_MODE);
|
||||
dock_clones.add_child (clone);
|
||||
|
||||
if (top)
|
||||
clone.y = actor.y - actor.height - clone_offset_y;
|
||||
else if (bottom)
|
||||
clone.y = actor.y + actor.height - clone_offset_y;
|
||||
}
|
||||
} else {
|
||||
foreach (var child in dock_clones.get_children ()) {
|
||||
var dock = (Clone) child;
|
||||
|
||||
dock.y = dock.source.y - clone_offset_y;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opening) {
|
||||
Timeout.add (290, () => {
|
||||
Timeout.add (ANIMATION_DURATION, () => {
|
||||
foreach (var container in window_containers_monitors) {
|
||||
container.visible = false;
|
||||
}
|
||||
@ -495,6 +554,8 @@ namespace Gala
|
||||
wm.window_group.show ();
|
||||
wm.top_window_group.show ();
|
||||
|
||||
dock_clones.destroy_all_children ();
|
||||
|
||||
wm.pop_modal (modal_proxy);
|
||||
|
||||
animating = false;
|
||||
@ -502,7 +563,7 @@ namespace Gala
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
Timeout.add (200, () => {
|
||||
Timeout.add (ANIMATION_DURATION, () => {
|
||||
animating = false;
|
||||
return false;
|
||||
});
|
||||
|
@ -73,8 +73,22 @@ namespace Gala
|
||||
|
||||
public bool overview_mode { get; construct; }
|
||||
|
||||
[CCode (notify = false)]
|
||||
public uint8 shadow_opacity {
|
||||
get {
|
||||
return shadow_effect != null ? shadow_effect.shadow_opacity : 255;
|
||||
}
|
||||
set {
|
||||
if (shadow_effect != null) {
|
||||
shadow_effect.shadow_opacity = value;
|
||||
queue_redraw ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DragDropAction? drag_action = null;
|
||||
Clone? clone = null;
|
||||
ShadowEffect? shadow_effect = null;
|
||||
|
||||
Actor prev_parent = null;
|
||||
int prev_index = -1;
|
||||
@ -195,7 +209,8 @@ namespace Gala
|
||||
#else
|
||||
var outer_rect = window.get_outer_rect ();
|
||||
#endif
|
||||
add_effect_with_name ("shadow", new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5));
|
||||
shadow_effect = new ShadowEffect (outer_rect.width, outer_rect.height, 40, 5);
|
||||
add_effect_with_name ("shadow", shadow_effect);
|
||||
#if HAS_MUTTER312
|
||||
window.size_changed.connect (update_shadow_size);
|
||||
#else
|
||||
@ -276,24 +291,20 @@ namespace Gala
|
||||
var outer_rect = window.get_outer_rect ();
|
||||
#endif
|
||||
|
||||
float offset_x = 0, offset_y = 0;
|
||||
var monitor_geom = window.get_screen ().get_monitor_geometry (window.get_monitor ());
|
||||
var offset_x = monitor_geom.x;
|
||||
var offset_y = monitor_geom.y;
|
||||
|
||||
var parent = get_parent ();
|
||||
if (parent != null) {
|
||||
// in overview_mode the parent has just been added to the stage, so the
|
||||
// transforme position is not set yet. However, the set position is correct
|
||||
// for overview anyway, so we can just use that.
|
||||
if (overview_mode)
|
||||
parent.get_position (out offset_x, out offset_y);
|
||||
else
|
||||
parent.get_transformed_position (out offset_x, out offset_y);
|
||||
}
|
||||
|
||||
set_easing_mode (AnimationMode.EASE_IN_OUT_CUBIC);
|
||||
set_easing_duration (animate ? 300 : 0);
|
||||
save_easing_state ();
|
||||
set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||
set_easing_duration (animate ? MultitaskingView.ANIMATION_DURATION : 0);
|
||||
|
||||
set_position (outer_rect.x - offset_x, outer_rect.y - offset_y);
|
||||
set_size (outer_rect.width, outer_rect.height);
|
||||
restore_easing_state ();
|
||||
|
||||
if (animate)
|
||||
toggle_shadow (false);
|
||||
|
||||
window_icon.opacity = 0;
|
||||
|
||||
@ -308,13 +319,17 @@ namespace Gala
|
||||
{
|
||||
slot = rect;
|
||||
|
||||
set_easing_duration (250);
|
||||
set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
save_easing_state ();
|
||||
set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||
set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||
|
||||
set_size (rect.width, rect.height);
|
||||
set_position (rect.x, rect.y);
|
||||
|
||||
window_icon.opacity = 255;
|
||||
restore_easing_state ();
|
||||
|
||||
toggle_shadow (true);
|
||||
|
||||
// for overview mode, windows may be faded out initially. Make sure
|
||||
// to fade those in.
|
||||
@ -430,6 +445,21 @@ namespace Gala
|
||||
}
|
||||
}
|
||||
|
||||
void toggle_shadow (bool show)
|
||||
{
|
||||
var shadow_transition = new PropertyTransition ("shadow-opacity");
|
||||
shadow_transition.duration = MultitaskingView.ANIMATION_DURATION;
|
||||
shadow_transition.remove_on_complete = true;
|
||||
shadow_transition.progress_mode = MultitaskingView.ANIMATION_MODE;
|
||||
|
||||
if (show)
|
||||
shadow_transition.interval = new Clutter.Interval (typeof (uint8), 0, 255);
|
||||
else
|
||||
shadow_transition.interval = new Clutter.Interval (typeof (uint8), 255, 0);
|
||||
|
||||
add_transition ("shadow-opacity", shadow_transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the window the delete signal and listen for new windows to be added
|
||||
* to the window's workspace, in which case we check if the new window is a
|
||||
|
@ -298,8 +298,8 @@ namespace Gala
|
||||
background.set_pivot_point (0.5f, pivotY);
|
||||
|
||||
background.save_easing_state ();
|
||||
background.set_easing_duration (250);
|
||||
background.set_easing_mode (AnimationMode.EASE_OUT_QUAD);
|
||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||
background.set_scale (scale, scale);
|
||||
background.restore_easing_state ();
|
||||
|
||||
@ -333,8 +333,8 @@ namespace Gala
|
||||
opened = false;
|
||||
|
||||
background.save_easing_state ();
|
||||
background.set_easing_duration (300);
|
||||
background.set_easing_mode (AnimationMode.EASE_IN_OUT_CUBIC);
|
||||
background.set_easing_duration (MultitaskingView.ANIMATION_DURATION);
|
||||
background.set_easing_mode (MultitaskingView.ANIMATION_MODE);
|
||||
background.set_scale (1, 1);
|
||||
background.restore_easing_state ();
|
||||
|
||||
|
@ -1241,6 +1241,8 @@ namespace Gala
|
||||
var primary = screen.get_primary_monitor ();
|
||||
var move_primary_only = InternalUtils.workspaces_only_on_primary ();
|
||||
var monitor_geom = screen.get_monitor_geometry (primary);
|
||||
var clone_offset_x = move_primary_only ? monitor_geom.x : 0;
|
||||
var clone_offset_y = move_primary_only ? monitor_geom.y : 0;
|
||||
|
||||
screen.get_size (out screen_width, out screen_height);
|
||||
|
||||
@ -1255,10 +1257,10 @@ namespace Gala
|
||||
parents = new List<Clutter.Actor> ();
|
||||
tmp_actors = new List<Clutter.Clone> ();
|
||||
|
||||
tmp_actors.append (main_container);
|
||||
tmp_actors.append (in_group);
|
||||
tmp_actors.append (out_group);
|
||||
tmp_actors.append (static_windows);
|
||||
tmp_actors.prepend (main_container);
|
||||
tmp_actors.prepend (in_group);
|
||||
tmp_actors.prepend (out_group);
|
||||
tmp_actors.prepend (static_windows);
|
||||
|
||||
window_group.add_child (main_container);
|
||||
|
||||
@ -1270,24 +1272,27 @@ namespace Gala
|
||||
} else
|
||||
wallpaper = background_group;
|
||||
|
||||
windows.append (wallpaper);
|
||||
parents.append (wallpaper.get_parent ());
|
||||
windows.prepend (wallpaper);
|
||||
parents.prepend (wallpaper.get_parent ());
|
||||
|
||||
var wallpaper_clone = new Clutter.Clone (wallpaper);
|
||||
tmp_actors.append (wallpaper_clone);
|
||||
tmp_actors.prepend (wallpaper_clone);
|
||||
|
||||
// pack all containers
|
||||
clutter_actor_reparent (wallpaper, main_container);
|
||||
main_container.add_child (wallpaper_clone);
|
||||
main_container.add_child (out_group);
|
||||
main_container.add_child (in_group);
|
||||
main_container.add_child (static_windows);
|
||||
|
||||
// if we have a move action, pack that window to the static ones
|
||||
if (moving != null) {
|
||||
var moving_actor = (WindowActor) moving.get_compositor_private ();
|
||||
|
||||
windows.append (moving_actor);
|
||||
parents.append (moving_actor.get_parent ());
|
||||
windows.prepend (moving_actor);
|
||||
parents.prepend (moving_actor.get_parent ());
|
||||
|
||||
moving_actor.set_translation (-clone_offset_x, -clone_offset_y, 0);
|
||||
clutter_actor_reparent (moving_actor, static_windows);
|
||||
}
|
||||
|
||||
@ -1295,6 +1300,7 @@ namespace Gala
|
||||
var from_has_fullscreened = false;
|
||||
var docks = new List<WindowActor> ();
|
||||
|
||||
// collect all windows and put them in the appropriate containers
|
||||
foreach (var actor in Compositor.get_window_actors (screen)) {
|
||||
if (actor.is_destroyed ())
|
||||
continue;
|
||||
@ -1310,13 +1316,14 @@ namespace Gala
|
||||
// only collect docks here that need to be displayed on both workspaces
|
||||
// all other windows will be collected below
|
||||
if (window.window_type == WindowType.DOCK) {
|
||||
docks.append (actor);
|
||||
docks.prepend (actor);
|
||||
} else {
|
||||
// windows that are on all workspaces will be faded out and back in
|
||||
windows.append (actor);
|
||||
parents.append (actor.get_parent ());
|
||||
windows.prepend (actor);
|
||||
parents.prepend (actor.get_parent ());
|
||||
clutter_actor_reparent (actor, static_windows);
|
||||
|
||||
actor.set_translation (-clone_offset_x, -clone_offset_y, 0);
|
||||
actor.save_easing_state ();
|
||||
actor.set_easing_duration (300);
|
||||
actor.opacity = 0;
|
||||
@ -1329,6 +1336,7 @@ namespace Gala
|
||||
if (window.get_workspace () == workspace_from) {
|
||||
windows.append (actor);
|
||||
parents.append (actor.get_parent ());
|
||||
actor.set_translation (-clone_offset_x, -clone_offset_y, 0);
|
||||
clutter_actor_reparent (actor, out_group);
|
||||
|
||||
if (window.fullscreen)
|
||||
@ -1337,6 +1345,7 @@ namespace Gala
|
||||
} else if (window.get_workspace () == workspace_to) {
|
||||
windows.append (actor);
|
||||
parents.append (actor.get_parent ());
|
||||
actor.set_translation (-clone_offset_x, -clone_offset_y, 0);
|
||||
clutter_actor_reparent (actor, in_group);
|
||||
|
||||
if (window.fullscreen)
|
||||
@ -1352,16 +1361,17 @@ namespace Gala
|
||||
foreach (var window in docks) {
|
||||
if (!to_has_fullscreened) {
|
||||
var clone = new SafeWindowClone (window.get_meta_window ());
|
||||
clone.x = window.x;
|
||||
clone.y = window.y;
|
||||
clone.x = window.x - clone_offset_x;
|
||||
clone.y = window.y - clone_offset_y;
|
||||
|
||||
in_group.add_child (clone);
|
||||
tmp_actors.append (clone);
|
||||
tmp_actors.prepend (clone);
|
||||
}
|
||||
|
||||
if (!from_has_fullscreened) {
|
||||
windows.append (window);
|
||||
parents.append (window.get_parent ());
|
||||
windows.prepend (window);
|
||||
parents.prepend (window.get_parent ());
|
||||
window.set_translation (-clone_offset_x, -clone_offset_y, 0);
|
||||
|
||||
clutter_actor_reparent (window, out_group);
|
||||
}
|
||||
@ -1369,7 +1379,7 @@ namespace Gala
|
||||
|
||||
main_container.clip_to_allocation = true;
|
||||
main_container.x = move_primary_only ? monitor_geom.x : 0;
|
||||
main_container.y = move_primary_only ? monitor_geom.x : 0;
|
||||
main_container.y = move_primary_only ? monitor_geom.y : 0;
|
||||
main_container.width = move_primary_only ? monitor_geom.width : screen_width;
|
||||
main_container.height = move_primary_only ? monitor_geom.height : screen_height;
|
||||
|
||||
@ -1400,10 +1410,10 @@ namespace Gala
|
||||
wallpaper.set_easing_duration (animation_duration);
|
||||
|
||||
out_group.x = x2;
|
||||
in_group.x = move_primary_only ? monitor_geom.x : 0;
|
||||
in_group.x = 0;
|
||||
|
||||
wallpaper.x = x2;
|
||||
wallpaper_clone.x = move_primary_only ? monitor_geom.x : 0;
|
||||
wallpaper_clone.x = 0;
|
||||
wallpaper.restore_easing_state ();
|
||||
|
||||
var transition = in_group.get_transition ("x");
|
||||
@ -1423,6 +1433,7 @@ namespace Gala
|
||||
|
||||
for (var i = 0; i < windows.length (); i++) {
|
||||
var actor = windows.nth_data (i);
|
||||
actor.set_translation (0, 0, 0);
|
||||
|
||||
// to maintain the correct order of monitor, we need to insert the Background
|
||||
// back manually
|
||||
|
Loading…
Reference in New Issue
Block a user