workspacesView: Use SwipeTracker
Replace existing panning, touchpad scrolling and four-finger gesture by SwipeTracker. Change programmatic workspace animation to use easeOutCubic interpolator to match the gesture. Also change the dragging distance to always match the current monitor. Fixes touchpad parts of https://gitlab.gnome.org/GNOME/gnome-shell/issues/1338 https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/826
This commit is contained in:
parent
a0c0e52229
commit
a11f417cd0
@ -4,7 +4,7 @@
|
|||||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const WindowManager = imports.ui.windowManager;
|
const SwipeTracker = imports.ui.swipeTracker;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
var WORKSPACE_SWITCH_TIME = 250;
|
var WORKSPACE_SWITCH_TIME = 250;
|
||||||
@ -79,7 +79,6 @@ class WorkspacesView extends WorkspacesViewBase {
|
|||||||
super._init(monitorIndex);
|
super._init(monitorIndex);
|
||||||
|
|
||||||
this._animating = false; // tweening
|
this._animating = false; // tweening
|
||||||
this._scrolling = false; // swipe-scrolling
|
|
||||||
this._gestureActive = false; // touch(pad) gestures
|
this._gestureActive = false; // touch(pad) gestures
|
||||||
|
|
||||||
this._scrollAdjustment = scrollAdjustment;
|
this._scrollAdjustment = scrollAdjustment;
|
||||||
@ -183,7 +182,7 @@ class WorkspacesView extends WorkspacesViewBase {
|
|||||||
if (showAnimation) {
|
if (showAnimation) {
|
||||||
let easeParams = Object.assign(params, {
|
let easeParams = Object.assign(params, {
|
||||||
duration: WORKSPACE_SWITCH_TIME,
|
duration: WORKSPACE_SWITCH_TIME,
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
||||||
});
|
});
|
||||||
// we have to call _updateVisibility() once before the
|
// we have to call _updateVisibility() once before the
|
||||||
// animation and once afterwards - it does not really
|
// animation and once afterwards - it does not really
|
||||||
@ -211,7 +210,7 @@ class WorkspacesView extends WorkspacesViewBase {
|
|||||||
for (let w = 0; w < this._workspaces.length; w++) {
|
for (let w = 0; w < this._workspaces.length; w++) {
|
||||||
let workspace = this._workspaces[w];
|
let workspace = this._workspaces[w];
|
||||||
|
|
||||||
if (this._animating || this._scrolling || this._gestureActive)
|
if (this._animating || this._gestureActive)
|
||||||
workspace.show();
|
workspace.show();
|
||||||
else if (this._inDrag)
|
else if (this._inDrag)
|
||||||
workspace.visible = Math.abs(w - active) <= 1;
|
workspace.visible = Math.abs(w - active) <= 1;
|
||||||
@ -268,18 +267,6 @@ class WorkspacesView extends WorkspacesViewBase {
|
|||||||
workspaceManager.disconnect(this._reorderWorkspacesId);
|
workspaceManager.disconnect(this._reorderWorkspacesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
startSwipeScroll() {
|
|
||||||
this._scrolling = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
endSwipeScroll() {
|
|
||||||
this._scrolling = false;
|
|
||||||
|
|
||||||
// Make sure title captions etc are shown as necessary
|
|
||||||
this._updateWorkspaceActors(true);
|
|
||||||
this._updateVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
startTouchGesture() {
|
startTouchGesture() {
|
||||||
this._gestureActive = true;
|
this._gestureActive = true;
|
||||||
}
|
}
|
||||||
@ -395,12 +382,6 @@ class ExtraWorkspaceView extends WorkspacesViewBase {
|
|||||||
this._workspace.syncStacking(stackIndices);
|
this._workspace.syncStacking(stackIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
startSwipeScroll() {
|
|
||||||
}
|
|
||||||
|
|
||||||
endSwipeScroll() {
|
|
||||||
}
|
|
||||||
|
|
||||||
startTouchGesture() {
|
startTouchGesture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,42 +419,14 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
});
|
});
|
||||||
Main.overview.addAction(clickAction);
|
Main.overview.addAction(clickAction);
|
||||||
this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
||||||
|
this._clickAction = clickAction;
|
||||||
|
|
||||||
let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER });
|
this._swipeTracker = new SwipeTracker.SwipeTracker(
|
||||||
panAction.connect('pan', this._onPan.bind(this));
|
Main.layoutManager.overviewGroup, Shell.ActionMode.OVERVIEW);
|
||||||
panAction.connect('gesture-begin', () => {
|
this._swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
|
||||||
if (this._workspacesOnlyOnPrimary) {
|
this._swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
|
||||||
let event = Clutter.get_current_event();
|
this._swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
|
||||||
if (this._getMonitorIndexForEvent(event) != this._primaryIndex)
|
this.bind_property('mapped', this._swipeTracker, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._startSwipeScroll();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
panAction.connect('gesture-cancel', () => {
|
|
||||||
clickAction.release();
|
|
||||||
this._endSwipeScroll();
|
|
||||||
});
|
|
||||||
panAction.connect('gesture-end', () => {
|
|
||||||
clickAction.release();
|
|
||||||
this._endSwipeScroll();
|
|
||||||
});
|
|
||||||
Main.overview.addAction(panAction);
|
|
||||||
this.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
|
|
||||||
let allowedModes = Shell.ActionMode.OVERVIEW;
|
|
||||||
let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
|
|
||||||
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
|
|
||||||
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
|
|
||||||
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
|
|
||||||
Main.overview.addAction(switchGesture);
|
|
||||||
this.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
|
|
||||||
switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
|
|
||||||
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
|
|
||||||
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
|
|
||||||
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
|
|
||||||
|
|
||||||
this._primaryIndex = Main.layoutManager.primaryIndex;
|
this._primaryIndex = Main.layoutManager.primaryIndex;
|
||||||
this._workspacesViews = [];
|
this._workspacesViews = [];
|
||||||
@ -491,7 +444,6 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
|
|
||||||
this._fullGeometry = null;
|
this._fullGeometry = null;
|
||||||
|
|
||||||
this._scrolling = false; // swipe-scrolling
|
|
||||||
this._gestureActive = false; // touch(pad) gestures
|
this._gestureActive = false; // touch(pad) gestures
|
||||||
this._canScroll = true; // limiting scrolling speed
|
this._canScroll = true; // limiting scrolling speed
|
||||||
|
|
||||||
@ -528,7 +480,7 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
|
_activeWorkspaceChanged(_wm, _from, _to, _direction) {
|
||||||
if (this._scrolling)
|
if (this._gestureActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._scrollToActive();
|
this._scrollToActive();
|
||||||
@ -542,77 +494,89 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateScrollAdjustment(index) {
|
_updateScrollAdjustment(index) {
|
||||||
if (this._scrolling || this._gestureActive)
|
if (this._gestureActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._scrollAdjustment.ease(index, {
|
this._scrollAdjustment.ease(index, {
|
||||||
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
||||||
duration: WORKSPACE_SWITCH_TIME,
|
duration: WORKSPACE_SWITCH_TIME,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPan(action) {
|
_directionForProgress(progress) {
|
||||||
let [dist_, dx, dy] = action.get_motion_delta(0);
|
if (global.workspace_manager.layout_rows === -1) {
|
||||||
|
return progress > 0
|
||||||
|
? Meta.MotionDirection.DOWN
|
||||||
|
: Meta.MotionDirection.UP;
|
||||||
|
} else if (this.text_direction === Clutter.TextDirection.RTL) {
|
||||||
|
return progress > 0
|
||||||
|
? Meta.MotionDirection.LEFT
|
||||||
|
: Meta.MotionDirection.RIGHT;
|
||||||
|
} else {
|
||||||
|
return progress > 0
|
||||||
|
? Meta.MotionDirection.RIGHT
|
||||||
|
: Meta.MotionDirection.LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_switchWorkspaceBegin(tracker, monitor) {
|
||||||
|
if (this._workspacesOnlyOnPrimary && monitor !== this._primaryIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let workspaceManager = global.workspace_manager;
|
||||||
let adjustment = this._scrollAdjustment;
|
let adjustment = this._scrollAdjustment;
|
||||||
if (global.workspace_manager.layout_rows == -1)
|
if (this._gestureActive)
|
||||||
adjustment.value -= (dy / this.height) * adjustment.page_size;
|
adjustment.remove_transition('value');
|
||||||
else if (this.text_direction == Clutter.TextDirection.RTL)
|
|
||||||
adjustment.value += (dx / this.width) * adjustment.page_size;
|
|
||||||
else
|
|
||||||
adjustment.value -= (dx / this.width) * adjustment.page_size;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_startSwipeScroll() {
|
tracker.orientation = workspaceManager.layout_rows !== -1
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
? Clutter.Orientation.HORIZONTAL
|
||||||
this._workspacesViews[i].startSwipeScroll();
|
: Clutter.Orientation.VERTICAL;
|
||||||
this._scrolling = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_endSwipeScroll() {
|
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
|
||||||
this._workspacesViews[i].endSwipeScroll();
|
|
||||||
this._scrolling = false;
|
|
||||||
this._scrollToActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
_startTouchGesture() {
|
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||||
this._workspacesViews[i].startTouchGesture();
|
this._workspacesViews[i].startTouchGesture();
|
||||||
|
|
||||||
|
let monitors = Main.layoutManager.monitors;
|
||||||
|
let geometry = monitor === this._primaryIndex
|
||||||
|
? this._fullGeometry : monitors[monitor];
|
||||||
|
let distance = global.workspace_manager.layout_rows === -1
|
||||||
|
? geometry.height : geometry.width;
|
||||||
|
|
||||||
|
let progress = adjustment.value / adjustment.page_size;
|
||||||
|
let points = Array.from(
|
||||||
|
{ length: workspaceManager.n_workspaces }, (v, i) => i);
|
||||||
|
|
||||||
|
tracker.confirmSwipe(distance, points, progress, Math.round(progress));
|
||||||
|
|
||||||
this._gestureActive = true;
|
this._gestureActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_switchWorkspaceUpdate(tracker, progress) {
|
||||||
|
let adjustment = this._scrollAdjustment;
|
||||||
|
adjustment.value = progress * adjustment.page_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
_switchWorkspaceEnd(tracker, duration, endProgress) {
|
||||||
|
this._clickAction.release();
|
||||||
|
|
||||||
|
let workspaceManager = global.workspace_manager;
|
||||||
|
let activeWorkspace = workspaceManager.get_active_workspace();
|
||||||
|
let newWs = workspaceManager.get_workspace_by_index(endProgress);
|
||||||
|
|
||||||
|
this._scrollAdjustment.ease(endProgress, {
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
||||||
|
duration,
|
||||||
|
onComplete: () => {
|
||||||
|
if (newWs !== activeWorkspace)
|
||||||
|
newWs.activate(global.get_current_time());
|
||||||
|
this._endTouchGesture();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_endTouchGesture() {
|
_endTouchGesture() {
|
||||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||||
this._workspacesViews[i].endTouchGesture();
|
this._workspacesViews[i].endTouchGesture();
|
||||||
this._gestureActive = false;
|
this._gestureActive = false;
|
||||||
this._scrollToActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSwitchWorkspaceMotion(action, xRel, yRel) {
|
|
||||||
// We don't have a way to hook into start of touchpad actions,
|
|
||||||
// luckily this is safe to call repeatedly.
|
|
||||||
this._startTouchGesture();
|
|
||||||
|
|
||||||
let workspaceManager = global.workspace_manager;
|
|
||||||
let active = workspaceManager.get_active_workspace_index();
|
|
||||||
let adjustment = this._scrollAdjustment;
|
|
||||||
if (workspaceManager.layout_rows == -1)
|
|
||||||
adjustment.value = (active - yRel / this.height) * adjustment.page_size;
|
|
||||||
else if (this.text_direction == Clutter.TextDirection.RTL)
|
|
||||||
adjustment.value = (active + xRel / this.width) * adjustment.page_size;
|
|
||||||
else
|
|
||||||
adjustment.value = (active - xRel / this.width) * adjustment.page_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSwitchWorkspaceActivated(action, direction) {
|
|
||||||
let workspaceManager = global.workspace_manager;
|
|
||||||
let activeWorkspace = workspaceManager.get_active_workspace();
|
|
||||||
let newWs = activeWorkspace.get_neighbor(direction);
|
|
||||||
if (newWs != activeWorkspace)
|
|
||||||
newWs.activate(global.get_current_time());
|
|
||||||
|
|
||||||
this._endTouchGesture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vfunc_navigate_focus(from, direction) {
|
vfunc_navigate_focus(from, direction) {
|
||||||
@ -692,8 +656,6 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
else
|
else
|
||||||
view = new WorkspacesView(i, this._scrollAdjustment);
|
view = new WorkspacesView(i, this._scrollAdjustment);
|
||||||
|
|
||||||
view.connect('scroll-event', this._onScrollEvent.bind(this));
|
|
||||||
|
|
||||||
// HACK: Avoid spurious allocation changes while updating views
|
// HACK: Avoid spurious allocation changes while updating views
|
||||||
view.hide();
|
view.hide();
|
||||||
|
|
||||||
@ -793,6 +755,9 @@ class WorkspacesDisplay extends St.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onScrollEvent(actor, event) {
|
_onScrollEvent(actor, event) {
|
||||||
|
if (this._swipeTracker.canHandleScrollEvent(event))
|
||||||
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
|
||||||
if (!this.mapped)
|
if (!this.mapped)
|
||||||
return Clutter.EVENT_PROPAGATE;
|
return Clutter.EVENT_PROPAGATE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user