overview: Make 3fg vertical swipes bring overview and app grid

The gesture internally manipulates the main adjustment so one swipe
up brings up the overview, and a second swipe up brings the app
grid. The gesture also works in the other direction to get out of
the overview.

Internally, this is delegated on the OverviewControls, so the
adjustment is not leaked out of there. This however meant open
coding the gesture interaction so it can be directed from
overview.js code.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1643>
This commit is contained in:
Carlos Garnacho 2021-01-04 16:23:45 +01:00
parent ddb8782179
commit cd506d45ef
2 changed files with 93 additions and 0 deletions

View File

@ -14,6 +14,7 @@ const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const SwipeTracker = imports.ui.swipeTracker;
const WindowManager = imports.ui.windowManager;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
@ -117,6 +118,10 @@ class OverviewActor extends St.BoxLayout {
get viewSelector() {
return this._controls.viewSelector;
}
get controls() {
return this._controls;
}
});
var Overview = class {
@ -233,6 +238,15 @@ var Overview = class {
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
this.toggle.bind(this));
const swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
{ allowDrag: false, allowScroll: false });
swipeTracker.orientation = Clutter.Orientation.VERTICAL;
swipeTracker.connect('begin', this._gestureBegin.bind(this));
swipeTracker.connect('update', this._gestureUpdate.bind(this));
swipeTracker.connect('end', this._gestureEnd.bind(this));
this._swipeTracker = swipeTracker;
}
addSearchProvider(provider) {
@ -365,6 +379,44 @@ var Overview = class {
this.emit('windows-restacked', stackIndices);
}
_gestureBegin(tracker) {
this._overview.controls.gestureBegin(tracker);
}
_gestureUpdate(tracker, progress) {
if (!this._shown) {
Meta.disable_unredirect_for_display(global.display);
this._shown = true;
this._visible = true;
this._visibleTarget = true;
this._animationInProgress = true;
Main.layoutManager.overviewGroup.set_child_above_sibling(
this._coverPane, null);
this._coverPane.show();
this.emit('showing');
Main.layoutManager.showOverview();
this._syncGrab();
}
this._overview.controls.gestureProgress(progress);
}
_gestureEnd(tracker, duration, endProgress) {
let onComplete;
if (endProgress === 0) {
this._shown = false;
this.emit('hiding');
onComplete = () => this._hideDone();
} else {
onComplete = () => this._showDone();
}
this._overview.controls.gestureEnd(endProgress, duration, onComplete);
}
beginItemDrag(source) {
this.emit('item-drag-begin', source);
this._inItemDrag = true;

View File

@ -583,6 +583,47 @@ class ControlsManager extends St.Widget {
return this.layoutManager.getWorkspacesBoxForState(state);
}
gestureBegin(tracker) {
const baseDistance = global.screen_height;
const progress = this._stateAdjustment.value;
const points = [
ControlsState.HIDDEN,
ControlsState.WINDOW_PICKER,
ControlsState.APP_GRID,
];
const transition = this._stateAdjustment.get_transition('value');
const cancelProgress = transition
? transition.get_interval().peek_final_value()
: Math.round(progress);
tracker.confirmSwipe(baseDistance, points, progress, cancelProgress);
this._workspacesDisplay.prepareToEnterOverview();
this._searchController.prepareToEnterOverview();
this._stateAdjustment.gestureInProgress = true;
}
gestureProgress(progress) {
this._stateAdjustment.value = progress;
}
gestureEnd(target, duration, onComplete) {
if (target === ControlsState.HIDDEN)
this._workspacesDisplay.prepareToLeaveOverview();
this.dash.showAppsButton.checked =
target === ControlsState.APP_GRID;
this._stateAdjustment.remove_transition('value');
this._stateAdjustment.ease(target, {
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete,
});
this._stateAdjustment.gestureInProgress = false;
}
get searchEntry() {
return this._searchEntry;
}