overview: Implement startup animation
The new startup animation consists of rising the Dash from the bottom, falling the search entry from the ceiling, and going from HIDDEN to WINDOW_PICKER with an opacity applied. One little trick from IconGridLayout was added to ControlsManagerLayout, which is a promises-based wait for allocation. This is required to make sure that the transformed position of the search entry is valid, which is only the case right after an allocation. This animation also ensures that the overview is shown right on startup. For session modes that do not have an overview, continue using the same fade + scale animation. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1678>
This commit is contained in:
parent
930d0b6151
commit
c4e43efb1e
@ -664,13 +664,18 @@ var LayoutManager = GObject.registerClass({
|
|||||||
this.keyboardBox.hide();
|
this.keyboardBox.hide();
|
||||||
|
|
||||||
let monitor = this.primaryMonitor;
|
let monitor = this.primaryMonitor;
|
||||||
let x = monitor.x + monitor.width / 2.0;
|
|
||||||
let y = monitor.y + monitor.height / 2.0;
|
|
||||||
|
|
||||||
this.uiGroup.set_pivot_point(x / global.screen_width,
|
if (!Main.sessionMode.hasOverview) {
|
||||||
y / global.screen_height);
|
const x = monitor.x + monitor.width / 2.0;
|
||||||
this.uiGroup.scale_x = this.uiGroup.scale_y = 0.75;
|
const y = monitor.y + monitor.height / 2.0;
|
||||||
this.uiGroup.opacity = 0;
|
|
||||||
|
this.uiGroup.set_pivot_point(
|
||||||
|
x / global.screen_width,
|
||||||
|
y / global.screen_height);
|
||||||
|
this.uiGroup.scale_x = this.uiGroup.scale_y = 0.75;
|
||||||
|
this.uiGroup.opacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height);
|
global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height);
|
||||||
|
|
||||||
await this._updateBackgrounds();
|
await this._updateBackgrounds();
|
||||||
@ -700,14 +705,19 @@ var LayoutManager = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_startupAnimationSession() {
|
_startupAnimationSession() {
|
||||||
this.uiGroup.ease({
|
const onComplete = () => this._startupAnimationComplete();
|
||||||
scale_x: 1,
|
if (Main.sessionMode.hasOverview) {
|
||||||
scale_y: 1,
|
Main.overview.runStartupAnimation(onComplete);
|
||||||
opacity: 255,
|
} else {
|
||||||
duration: STARTUP_ANIMATION_TIME,
|
this.uiGroup.ease({
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
scale_x: 1,
|
||||||
onComplete: () => this._startupAnimationComplete(),
|
scale_y: 1,
|
||||||
});
|
opacity: 255,
|
||||||
|
duration: STARTUP_ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
onComplete,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_startupAnimationComplete() {
|
_startupAnimationComplete() {
|
||||||
|
@ -107,6 +107,10 @@ class OverviewActor extends St.BoxLayout {
|
|||||||
this._controls.animateFromOverview(callback);
|
this._controls.animateFromOverview(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runStartupAnimation(callback) {
|
||||||
|
this._controls.runStartupAnimation(callback);
|
||||||
|
}
|
||||||
|
|
||||||
get dash() {
|
get dash() {
|
||||||
return this._controls.dash;
|
return this._controls.dash;
|
||||||
}
|
}
|
||||||
@ -647,6 +651,23 @@ var Overview = class {
|
|||||||
this._show(OverviewControls.ControlsState.APP_GRID);
|
this._show(OverviewControls.ControlsState.APP_GRID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runStartupAnimation(callback) {
|
||||||
|
this._shown = true;
|
||||||
|
this._visible = true;
|
||||||
|
this._visibleTarget = true;
|
||||||
|
Main.layoutManager.showOverview();
|
||||||
|
this._syncGrab();
|
||||||
|
|
||||||
|
Meta.disable_unredirect_for_display(global.display);
|
||||||
|
|
||||||
|
this.emit('showing');
|
||||||
|
|
||||||
|
this._overview.runStartupAnimation(() => {
|
||||||
|
this.emit('shown');
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getShowAppsButton() {
|
getShowAppsButton() {
|
||||||
logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
|
logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
|
||||||
'use \'dash.showAppsButton\' property instead'));
|
'use \'dash.showAppsButton\' property instead'));
|
||||||
|
@ -5,6 +5,7 @@ const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
|
|||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const Dash = imports.ui.dash;
|
const Dash = imports.ui.dash;
|
||||||
|
const Layout = imports.ui.layout;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const SearchController = imports.ui.searchController;
|
const SearchController = imports.ui.searchController;
|
||||||
@ -41,6 +42,7 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
|
|||||||
this._dash = dash;
|
this._dash = dash;
|
||||||
|
|
||||||
this._cachedWorkspaceBoxes = new Map();
|
this._cachedWorkspaceBoxes = new Map();
|
||||||
|
this._postAllocationCallbacks = [];
|
||||||
|
|
||||||
stateAdjustment.connect('notify::value', () => this.layout_changed());
|
stateAdjustment.connect('notify::value', () => this.layout_changed());
|
||||||
}
|
}
|
||||||
@ -100,6 +102,14 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
|
|||||||
return appDisplayBox;
|
return appDisplayBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_runPostAllocation() {
|
||||||
|
if (this._postAllocationCallbacks.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._postAllocationCallbacks.forEach(cb => cb());
|
||||||
|
this._postAllocationCallbacks = [];
|
||||||
|
}
|
||||||
|
|
||||||
vfunc_set_container(container) {
|
vfunc_set_container(container) {
|
||||||
this._container = container;
|
this._container = container;
|
||||||
this.hookup_style(container);
|
this.hookup_style(container);
|
||||||
@ -192,6 +202,14 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
|
|||||||
childBox.set_size(width, availableHeight);
|
childBox.set_size(width, availableHeight);
|
||||||
|
|
||||||
this._searchController.allocate(childBox);
|
this._searchController.allocate(childBox);
|
||||||
|
|
||||||
|
this._runPostAllocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureAllocation() {
|
||||||
|
this.layout_changed();
|
||||||
|
return new Promise(
|
||||||
|
resolve => this._postAllocationCallbacks.push(resolve));
|
||||||
}
|
}
|
||||||
|
|
||||||
getWorkspacesBoxForState(state) {
|
getWorkspacesBoxForState(state) {
|
||||||
@ -695,6 +713,60 @@ class ControlsManager extends St.Widget {
|
|||||||
this._stateAdjustment.gestureInProgress = false;
|
this._stateAdjustment.gestureInProgress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async runStartupAnimation(callback) {
|
||||||
|
this._ignoreShowAppsButtonToggle = true;
|
||||||
|
|
||||||
|
this._searchController.prepareToEnterOverview();
|
||||||
|
this._workspacesDisplay.prepareToEnterOverview();
|
||||||
|
|
||||||
|
this._stateAdjustment.value = ControlsState.HIDDEN;
|
||||||
|
this._stateAdjustment.ease(ControlsState.WINDOW_PICKER, {
|
||||||
|
duration: Overview.ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dash.showAppsButton.checked = false;
|
||||||
|
this._ignoreShowAppsButtonToggle = false;
|
||||||
|
|
||||||
|
// Set the opacity here to avoid a 1-frame flicker
|
||||||
|
this.opacity = 0;
|
||||||
|
|
||||||
|
// We can't run the animation before the first allocation happens
|
||||||
|
await this.layout_manager.ensureAllocation();
|
||||||
|
|
||||||
|
const { STARTUP_ANIMATION_TIME } = Layout;
|
||||||
|
|
||||||
|
// Opacity
|
||||||
|
this.ease({
|
||||||
|
opacity: 255,
|
||||||
|
duration: STARTUP_ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.LINEAR,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Search bar falls from the ceiling
|
||||||
|
const { primaryMonitor } = Main.layoutManager;
|
||||||
|
const [, y] = this._searchEntryBin.get_transformed_position();
|
||||||
|
const yOffset = y - primaryMonitor.y;
|
||||||
|
|
||||||
|
this._searchEntryBin.translation_y = -(yOffset + this._searchEntryBin.height);
|
||||||
|
this._searchEntryBin.ease({
|
||||||
|
translation_y: 0,
|
||||||
|
duration: STARTUP_ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
});
|
||||||
|
|
||||||
|
// The Dash rises from the bottom. This is the last animation to finish,
|
||||||
|
// so run the callback there.
|
||||||
|
this.dash.translation_y = this.dash.height;
|
||||||
|
this.dash.ease({
|
||||||
|
translation_y: 0,
|
||||||
|
delay: STARTUP_ANIMATION_TIME,
|
||||||
|
duration: STARTUP_ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
onComplete: () => callback(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get searchEntry() {
|
get searchEntry() {
|
||||||
return this._searchEntry;
|
return this._searchEntry;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user