[gnome-shell/wip/carlosg/interactive-workspace-switching: 4/4] windowManager: Make workspace switching gestures follow motion
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/carlosg/interactive-workspace-switching: 4/4] windowManager: Make workspace switching gestures follow motion
- Date: Mon, 30 Jul 2018 21:23:41 +0000 (UTC)
commit ebe6f59d7e3c3b520b5d52ddf39be6a64ec3f80b
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Jul 13 23:38:03 2018 +0200
windowManager: Make workspace switching gestures follow motion
When 4fg swipe motion happens, set up early the workspace switching
animation with all surrounding workspaces. This allows us to move
all content back and forth in any direction. This works on both
touchcreens and touchpads.
When the gesture is activated, the same data is reused to follow
up with the tween animation.
The threshold has been also doubled, it was fairly small to start
with, and feels better now that workspaces stick to fingers.
https://bugzilla.gnome.org/show_bug.cgi?id=788994
js/ui/windowManager.js | 126 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 107 insertions(+), 19 deletions(-)
---
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 18f393dda..a88d4f9a0 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -3,6 +3,7 @@
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@@ -34,6 +35,7 @@ var WINDOW_ANIMATION_TIME = 0.25;
var DIM_BRIGHTNESS = -0.3;
var DIM_TIME = 0.500;
var UNDIM_TIME = 0.250;
+var MOTION_THRESHOLD = 100;
var ONE_SECOND = 1000; // in ms
@@ -495,13 +497,8 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
},
_checkActivated() {
- const MOTION_THRESHOLD = 50;
- let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
let dir;
- if ((allowedModes & Main.actionMode) == 0)
- return;
-
if (this._dy < -MOTION_THRESHOLD)
dir = Meta.MotionDirection.DOWN;
else if (this._dy > MOTION_THRESHOLD)
@@ -511,26 +508,35 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
else if (this._dx > MOTION_THRESHOLD)
dir = Meta.MotionDirection.LEFT;
else
- return;
+ return false;
this.emit('activated', dir);
+ return true;
},
_handleEvent(actor, event) {
+ let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
+
if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
return Clutter.EVENT_PROPAGATE;
if (event.get_touchpad_gesture_finger_count() != 4)
return Clutter.EVENT_PROPAGATE;
+ if ((allowedModes & Main.actionMode) == 0)
+ return Clutter.EVENT_PROPAGATE;
+
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
let [dx, dy] = event.get_gesture_motion_delta();
- this._dx += dx;
- this._dy += dy;
+ // Scale deltas up a bit to make it feel snappier
+ this._dx += dx * 2;
+ this._dy += dy * 2;
+ this.emit('motion', this._dx, this._dy);
} else {
- if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END)
- this._checkActivated();
+ if ((event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END && ! this._checkActivated())
||
+ event.get_gesture_phase() == Clutter.TouchpadGesturePhase.CANCEL)
+ this.emit('cancel');
this._dx = 0;
this._dy = 0;
@@ -544,14 +550,14 @@ Signals.addSignalMethods(TouchpadWorkspaceSwitchAction.prototype);
var WorkspaceSwitchAction = new Lang.Class({
Name: 'WorkspaceSwitchAction',
Extends: Clutter.SwipeAction,
- Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] } },
+ Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] },
+ 'motion': { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
+ 'cancel': { param_types: [] }},
_init() {
- const MOTION_THRESHOLD = 50;
-
this.parent();
this.set_n_touch_points(4);
- this.set_threshold_trigger_distance(MOTION_THRESHOLD, MOTION_THRESHOLD);
+ this._swept = false;
global.display.connect('grab-op-begin', () => {
this.cancel();
@@ -561,13 +567,35 @@ var WorkspaceSwitchAction = new Lang.Class({
vfunc_gesture_prepare(actor) {
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
+ this._swept = false;
+
if (!this.parent(actor))
return false;
return (allowedModes & Main.actionMode);
},
- vfunc_swept(actor, direction) {
+ vfunc_gesture_progress(actor) {
+ let [x, y] = this.get_motion_coords(0);
+ let [xPress, yPress] = this.get_press_coords(0);
+ this.emit('motion', x - xPress, y - yPress);
+ return true;
+ },
+
+ vfunc_gesture_cancel(actor) {
+ if (!this._swept)
+ this.emit('cancel');
+ },
+
+ vfunc_swipe(actor, direction) {
+ let [x, y] = this.get_motion_coords(0);
+ let [xPress, yPress] = this.get_press_coords(0);
+ if (Math.abs(x - xPress) < MOTION_THRESHOLD &&
+ Math.abs(y - yPress) < MOTION_THRESHOLD) {
+ this.emit('cancel');
+ return;
+ }
+
let dir;
if (direction & Clutter.SwipeDirection.UP)
@@ -579,6 +607,7 @@ var WorkspaceSwitchAction = new Lang.Class({
else if (direction & Clutter.SwipeDirection.RIGHT)
dir = Meta.MotionDirection.LEFT;
+ this._swept = true;
this.emit('activated', dir);
}
});
@@ -700,7 +729,14 @@ var WindowManager = new Lang.Class({
this._isWorkspacePrepended = false;
this._switchData = null;
- this._shellwm.connect('kill-switch-workspace', this._switchWorkspaceDone.bind(this));
+ this._shellwm.connect('kill-switch-workspace', (shellwm) => {
+ if (this._switchData) {
+ if (this._switchData.inProgress)
+ this._switchWorkspaceDone(shellwm);
+ else if (!this._switchData.gestureActivated)
+ this._finishWorkspaceSwitch(this._switchData);
+ }
+ });
this._shellwm.connect('kill-window-effects', (shellwm, actor) => {
this._minimizeWindowDone(shellwm, actor);
this._mapWindowDone(shellwm, actor);
@@ -982,12 +1018,16 @@ var WindowManager = new Lang.Class({
false, -1, 1);
let gesture = new WorkspaceSwitchAction();
+ gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
+ gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
global.stage.add_action(gesture);
// This is not a normal Clutter.GestureAction, doesn't need add_action()
gesture = new TouchpadWorkspaceSwitchAction(global.stage);
+ gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
+ gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
gesture = new AppSwitchAction();
gesture.connect('activated', this._switchApp.bind(this));
@@ -1016,11 +1056,52 @@ var WindowManager = new Lang.Class({
return this._currentPadOsd.actor;
},
+ _switchWorkspaceMotion(action, xRel, yRel) {
+ let workspaceManager = global.workspace_manager;
+ let activeWorkspace = workspaceManager.get_active_workspace();
+
+ if (!this._switchData)
+ this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
+
+ if (yRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.DOWN])
+ yRel = 0;
+ if (yRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.UP])
+ yRel = 0;
+ if (xRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.RIGHT])
+ xRel = 0;
+ if (xRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.LEFT])
+ xRel = 0;
+
+ this._switchData.container.set_position(xRel, yRel);
+ },
+
+ _switchWorkspaceCancel() {
+ if (!this._switchData || this._switchData.inProgress)
+ return;
+ let switchData = this._switchData;
+ this._switchData = null;
+ Tweener.addTween(switchData.container,
+ { x: 0,
+ y: 0,
+ time: WINDOW_ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onComplete: this._finishWorkspaceSwitch,
+ onCompleteScope: this,
+ onCompleteParams: [switchData],
+ });
+ },
+
_actionSwitchWorkspace(action, direction) {
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace.get_neighbor(direction);
- this.actionMoveWorkspace(newWs);
+
+ if (newWs == activeWorkspace) {
+ this._switchWorkspaceCancel();
+ } else {
+ this._switchData.gestureActivated = true;
+ this.actionMoveWorkspace(newWs);
+ }
},
_lookupIndex(windows, metaWindow) {
@@ -1762,6 +1843,8 @@ var WindowManager = new Lang.Class({
switchData.movingWindowBin = new Clutter.Actor();
switchData.windows = [];
switchData.surroundings = {};
+ switchData.gestureActivated = false;
+ switchData.inProgress = false;
switchData.container = new Clutter.Actor();
switchData.container.add_actor(switchData.curGroup);
@@ -1857,6 +1940,13 @@ var WindowManager = new Lang.Class({
return;
}
+ // If we come from a gesture, switchData will already be set,
+ // and we don't want to overwrite it.
+ if (!this._switchData)
+ this._prepareWorkspaceSwitch(from, to, direction);
+
+ this._switchData.inProgress = true;
+
let [xDest, yDest] = this._getPositionForDirection(direction);
/* @direction is the direction that the "camera" moves, so the
@@ -1866,8 +1956,6 @@ var WindowManager = new Lang.Class({
xDest = -xDest;
yDest = -yDest;
- this._prepareWorkspaceSwitch(from, to, direction);
-
Tweener.addTween(this._switchData.container,
{ x: xDest,
y: yDest,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]