Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animate nudge with clones #1803

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 142 additions & 72 deletions src/WindowManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -607,10 +607,15 @@ namespace Gala {
return;
}

animating_switch_workspace = true;

unowned var display = get_display ();
var scale = display.get_monitor_scale (display.get_primary_monitor ());
var nudge_gap = InternalUtils.scale_to_int (NUDGE_GAP, scale);
unowned var active_index = display.get_workspace_manager ().get_active_workspace_index ();
prepare_workspace_switch (active_index, active_index, direction);

var monitor_scale = display.get_monitor_scale (display.get_primary_monitor ());

var nudge_gap = InternalUtils.scale_to_int (NUDGE_GAP, monitor_scale);
float dest = 0;
if (!switch_workspace_with_gesture) {
dest = nudge_gap;
Expand All @@ -623,39 +628,66 @@ namespace Gala {
dest *= -1;
}

var animation_mode = Clutter.AnimationMode.EASE_OUT_CUBIC;

GestureTracker.OnUpdate on_animation_update = (percentage) => {
var x = GestureTracker.animation_value (0.0f, dest, percentage, true);
ui_group.translation_x = x.clamp (-nudge_gap, nudge_gap);
var x_out = GestureTracker.animation_value (0.0f, dest, percentage, true).clamp (-nudge_gap, nudge_gap);
out_group.x = x_out;
wallpaper.x = x_out;
};

GestureTracker.OnEnd on_animation_end = (percentage, cancel_action) => {
var nudge_gesture = new Clutter.PropertyTransition ("translation-x") {
duration = (AnimationDuration.NUDGE / 2),
remove_on_complete = true,
progress_mode = Clutter.AnimationMode.LINEAR
};
nudge_gesture.set_from_value (ui_group.translation_x);
nudge_gesture.set_to_value (0.0f);
ui_group.add_transition ("nudge", nudge_gesture);
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action, duration) => {
out_group.save_easing_state ();
out_group.set_easing_mode (animation_mode);
out_group.set_easing_duration (AnimationDuration.NUDGE / 2);

switch_workspace_with_gesture = false;
wallpaper.save_easing_state ();
wallpaper.set_easing_mode (animation_mode);
wallpaper.set_easing_duration (AnimationDuration.NUDGE / 2);

out_group.x = 0.0f;
out_group.restore_easing_state ();

wallpaper.x = 0.0f;
wallpaper.restore_easing_state ();

unowned var transition = out_group.get_transition ("x");
transition.completed.connect (() => {
switch_workspace_animation_finished (direction, false, true);
animating_switch_workspace = false;
});
};

if (!switch_workspace_with_gesture) {
double[] keyframes = { 0.5 };
GLib.Value[] x = { dest };

var nudge = new Clutter.KeyframeTransition ("translation-x") {
var out_group_nudge = new Clutter.KeyframeTransition ("translation-x") {
duration = AnimationDuration.NUDGE,
remove_on_complete = true,
progress_mode = Clutter.AnimationMode.EASE_IN_QUAD
};
nudge.set_from_value (0.0f);
nudge.set_to_value (0.0f);
nudge.set_key_frames (keyframes);
nudge.set_values (x);
out_group_nudge.set_from_value (0.0f);
out_group_nudge.set_to_value (0.0f);
out_group_nudge.set_key_frames (keyframes);
out_group_nudge.set_values (x);
out_group.add_transition ("nudge", out_group_nudge);

ui_group.add_transition ("nudge", nudge);
var wallpaper_nudge = new Clutter.KeyframeTransition ("translation-x") {
duration = AnimationDuration.NUDGE,
remove_on_complete = true,
progress_mode = Clutter.AnimationMode.EASE_IN_QUAD
};
wallpaper_nudge.set_from_value (0.0f);
wallpaper_nudge.set_to_value (0.0f);
wallpaper_nudge.set_key_frames (keyframes);
wallpaper_nudge.set_values (x);
wallpaper.add_transition ("nudge", wallpaper_nudge);

wallpaper_nudge.completed.connect (() => {
switch_workspace_animation_finished (direction, false, true);
animating_switch_workspace = false;
});
} else {
gesture_tracker.connect_handlers (null, (owned) on_animation_update, (owned) on_animation_end);
}
Expand Down Expand Up @@ -1858,23 +1890,14 @@ namespace Gala {
private List<Clutter.Actor>? parents;
private List<Clutter.Actor>? tmp_actors;
private ulong switch_workspace_window_created_id = 0;
private Clutter.Actor? out_group;
private Clutter.Actor? in_group;
private Clutter.Actor? wallpaper;
private Clutter.Actor? wallpaper_clone;

public override void switch_workspace (int from, int to, Meta.MotionDirection direction) {
if (!enable_animations
|| AnimationDuration.WORKSPACE_SWITCH == 0
|| (direction != Meta.MotionDirection.LEFT && direction != Meta.MotionDirection.RIGHT)
|| animating_switch_workspace
|| workspace_view.is_opened ()
|| window_overview.is_opened ()) {
animating_switch_workspace = false;
switch_workspace_completed ();
return;
}

animating_switch_workspace = true;

private void prepare_workspace_switch (int from, int to, Meta.MotionDirection direction) {
float screen_width, screen_height;
unowned Meta.Display display = get_display ();
unowned var display = get_display ();
var primary = display.get_primary_monitor ();
var move_primary_only = InternalUtils.workspaces_only_on_primary ();
var monitor_geom = display.get_monitor_geometry (primary);
Expand All @@ -1883,29 +1906,32 @@ namespace Gala {

display.get_size (out screen_width, out screen_height);

unowned Meta.WorkspaceManager manager = display.get_workspace_manager ();
unowned Meta.Workspace workspace_from = manager.get_workspace_by_index (from);
unowned Meta.Workspace workspace_to = manager.get_workspace_by_index (to);
unowned var manager = display.get_workspace_manager ();
unowned var workspace_from = manager.get_workspace_by_index (from);
unowned var workspace_to = from != to ? manager.get_workspace_by_index (to) : null;

var main_container = new Clutter.Actor ();
var background_actor = new Clutter.Clone (system_background.background_actor);
var static_windows = new Clutter.Actor ();
var in_group = new Clutter.Actor ();
var out_group = new Clutter.Actor ();
if (workspace_to != null) {
in_group = new Clutter.Actor ();
}
out_group = new Clutter.Actor ();
windows = new List<Meta.WindowActor> ();
parents = new List<Clutter.Actor> ();
tmp_actors = new List<Clutter.Clone> ();

tmp_actors.prepend (main_container);
tmp_actors.prepend (background_actor);
tmp_actors.prepend (in_group);
if (in_group != null) {
tmp_actors.prepend (in_group);
}
tmp_actors.prepend (out_group);
tmp_actors.prepend (static_windows);

window_group.add_child (main_container);

// prepare wallpaper
Clutter.Actor wallpaper;
if (move_primary_only) {
unowned var background = background_group.get_child_at_index (primary);
background.hide ();
Expand All @@ -1917,16 +1943,22 @@ namespace Gala {
wallpaper.add_effect (new Gala.ShadowEffect (40) { css_class = "workspace" });
tmp_actors.prepend (wallpaper);

var wallpaper_clone = new Clutter.Clone (wallpaper);
wallpaper_clone.add_effect (new Gala.ShadowEffect (40) { css_class = "workspace" });
tmp_actors.prepend (wallpaper_clone);
if (workspace_to != null) {
wallpaper_clone = new Clutter.Clone (wallpaper);
wallpaper_clone.add_effect (new Gala.ShadowEffect (40) { css_class = "workspace" });
tmp_actors.prepend (wallpaper_clone);
}

// pack all containers
main_container.add_child (background_actor);
main_container.add_child (wallpaper);
main_container.add_child (wallpaper_clone);
if (wallpaper_clone != null) {
main_container.add_child (wallpaper_clone);
}
main_container.add_child (out_group);
main_container.add_child (in_group);
if (in_group != null) {
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
Expand Down Expand Up @@ -1988,7 +2020,7 @@ namespace Gala {
if (window.fullscreen)
from_has_fullscreened = true;

} else if (window.get_workspace () == workspace_to) {
} else if (workspace_to != null && window.get_workspace () == workspace_to) {
windows.append (actor);
parents.append (actor.get_parent ());
actor.set_translation (-clone_offset_x, -clone_offset_y, 0);
Expand All @@ -2000,22 +2032,12 @@ namespace Gala {
}
}

// while a workspace is being switched mutter doesn't map windows
// TODO: currently only notifications are handled here, other windows should be too
switch_workspace_window_created_id = window_created.connect ((window) => {
if (window.window_type == Meta.WindowType.NOTIFICATION) {
unowned var actor = (Meta.WindowActor) window.get_compositor_private ();
clutter_actor_reparent (actor, notification_group);
notification_stack.show_notification (actor, enable_animations);
}
});

// make sure we don't add docks when there are fullscreened
// windows on one of the groups. Simply raising seems not to
// work, mutter probably reverts the order internally to match
// the display stack
foreach (var window in docks) {
if (!to_has_fullscreened) {
if (workspace_to != null && !to_has_fullscreened) {
var clone = new SafeWindowClone (window.get_meta_window ()) {
x = window.x - clone_offset_x,
y = window.y - clone_offset_y
Expand All @@ -2042,32 +2064,74 @@ namespace Gala {

var monitor_scale = display.get_monitor_scale (primary);
var x2 = move_primary_only ? monitor_geom.width : screen_width;
x2 += WORKSPACE_GAP * monitor_scale;
if (direction == Meta.MotionDirection.RIGHT)
if (workspace_to != null) {
x2 += WORKSPACE_GAP * monitor_scale;
}
if (direction == Meta.MotionDirection.RIGHT) {
x2 = -x2;
}

out_group.x = 0.0f;
wallpaper.x = 0.0f;
wallpaper.y += clone_offset_y;
in_group.x = -x2;
wallpaper_clone.x = -x2;
wallpaper_clone.y += clone_offset_y;
wallpaper.set_translation (-clone_offset_x, 0.0f, 0.0f);
wallpaper_clone.set_translation (-clone_offset_x, 0.0f, 0.0f);

if (in_group != null && wallpaper_clone != null) {
in_group.x = -x2;
wallpaper_clone.x = -x2;
wallpaper_clone.y += clone_offset_y;
wallpaper_clone.set_translation (-clone_offset_x, 0.0f, 0.0f);
}

// The wallpapers need to move upwards inside the container to match their
// original position before/after the transition.
if (move_primary_only) {
wallpaper.y = -monitor_geom.y;
wallpaper_clone.y = -monitor_geom.y;
if (wallpaper_clone != null) {
wallpaper_clone.y = -monitor_geom.y;
}
}

in_group.clip_to_allocation = out_group.clip_to_allocation = true;
in_group.width = out_group.width = move_primary_only ? monitor_geom.width : screen_width;
in_group.height = out_group.height = move_primary_only ? monitor_geom.height : screen_height;
out_group.clip_to_allocation = true;
out_group.width = move_primary_only ? monitor_geom.width : screen_width;
out_group.height = move_primary_only ? monitor_geom.height : screen_height;

if (in_group != null) {
in_group.clip_to_allocation = out_group.clip_to_allocation;
in_group.width = out_group.width;
in_group.height = out_group.height;
}
}

public override void switch_workspace (int from, int to, Meta.MotionDirection direction) {
if (!enable_animations
|| AnimationDuration.WORKSPACE_SWITCH == 0
|| (direction != Meta.MotionDirection.LEFT && direction != Meta.MotionDirection.RIGHT)
|| animating_switch_workspace
|| workspace_view.is_opened ()
|| window_overview.is_opened ()) {
animating_switch_workspace = false;
switch_workspace_completed ();
return;
}

animating_switch_workspace = true;

prepare_workspace_switch (from, to, direction);

// while a workspace is being switched mutter doesn't map windows
// TODO: currently only notifications are handled here, other windows should be too
switch_workspace_window_created_id = window_created.connect ((window) => {
if (window.window_type == Meta.WindowType.NOTIFICATION) {
unowned var actor = (Meta.WindowActor) window.get_compositor_private ();
clutter_actor_reparent (actor, notification_group);
notification_stack.show_notification (actor, enable_animations);
}
});

var animation_mode = Clutter.AnimationMode.EASE_OUT_CUBIC;

var x2 = -in_group.x;
GestureTracker.OnUpdate on_animation_update = (percentage) => {
var x_out = GestureTracker.animation_value (0.0f, x2, percentage, true);
var x_in = GestureTracker.animation_value (-x2, 0.0f, percentage, true);
Expand Down Expand Up @@ -2131,12 +2195,15 @@ namespace Gala {
}

private void switch_workspace_animation_finished (Meta.MotionDirection animation_direction,
bool cancel_action) {
bool cancel_action, bool is_nudge_animation = false) {
if (switch_workspace_window_created_id > 0) {
disconnect (switch_workspace_window_created_id);
switch_workspace_window_created_id = 0;
}
end_switch_workspace ();
if (!is_nudge_animation) {
switch_workspace_completed ();
}
animating_switch_workspace = cancel_action;

if (cancel_action) {
Expand Down Expand Up @@ -2209,10 +2276,13 @@ namespace Gala {
parents = null;
moving = null;

out_group = null;
in_group = null;
wallpaper = null;
wallpaper_clone = null;

switch_workspace_with_gesture = false;
animating_switch_workspace = false;

switch_workspace_completed ();
}

public override void kill_switch_workspace () {
Expand Down