workspace scroll: Add smooth scroll for touchpads

closes #74
This commit is contained in:
Tor Hedin Brønner
2018-07-29 14:52:22 +02:00
parent a1bda566df
commit c8678ea79f
2 changed files with 112 additions and 7 deletions

View File

@@ -1101,7 +1101,7 @@ class Spaces extends Map {
{y: Math.round(space.monitor.y
+ space.monitor.height/2),
time: 0.25,
transition: 'easeInOutQuad'
transition
});
} else {
if (direction === Meta.MotionDirection.DOWN)
@@ -1109,7 +1109,7 @@ class Spaces extends Map {
else
to = from - 1;
if (to < 0 || to >= mru.length) {
return true;
to = from;
}
newSpace = mru[to];
this.selectedSpace = newSpace;
@@ -1139,7 +1139,7 @@ class Spaces extends Map {
time: 0.25,
scale_x: scale + (to - i)*0.01,
scale_y: scale + (to - i)*0.01,
transition: 'easeInOutQuad',
transition
});
});

113
topbar.js
View File

@@ -149,6 +149,7 @@ class WorkspaceMenu extends PanelMenu.Button {
_finishWorkspaceSelect() {
this.state = "NORMAL";
this._enterbox.destroy();
delete this.selected;
delete this._enterbox;
delete this._navigator;
}
@@ -164,9 +165,11 @@ class WorkspaceMenu extends PanelMenu.Button {
this.state = "NORMAL";
}
if ((event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS)) {
if (this.state === "SCROLL") {
let type = event.type();
if ((type == Clutter.EventType.TOUCH_BEGIN ||
type == Clutter.EventType.BUTTON_PRESS)) {
if (['SCROLL', 'SMOOTH'].includes(this.state)) {
this._navigator.finish();
} else {
if (event.get_button() === Clutter.BUTTON_SECONDARY) {
@@ -184,10 +187,11 @@ class WorkspaceMenu extends PanelMenu.Button {
}
if (["NORMAL", "SCROLL"].includes(this.state) &&
event.type() === Clutter.EventType.SCROLL) {
type === Clutter.EventType.SCROLL) {
if (!this._navigator) {
this.state = 'SCROLL';
this._navigator = Navigator.getNavigator();
Tiling.spaces._initWorkspaceStack();
this._enterbox = new Clutter.Actor({reactive: true});
Main.uiGroup.add_actor(this._enterbox);
this._enterbox.set_position(panelBox.x, panelBox.y + panelBox.height + 20);
@@ -201,7 +205,14 @@ class WorkspaceMenu extends PanelMenu.Button {
});
}
let device = event.get_source_device();
// log(`source: ${device.get_device_type()}`);
let direction = event.get_scroll_direction();
if (direction === Clutter.ScrollDirection.SMOOTH
&& device.get_device_type() !== Clutter.InputDeviceType.POINTER_DEVICE) {
this.state = 'SMOOTH';
}
if (direction === Clutter.ScrollDirection.UP) {
Tiling.spaces.selectSpace(Meta.MotionDirection.DOWN);
}
@@ -210,6 +221,100 @@ class WorkspaceMenu extends PanelMenu.Button {
}
}
if (this.state === 'SMOOTH' && type === Clutter.EventType.SCROLL
&& event.get_scroll_direction() === Clutter.ScrollDirection.SMOOTH) {
let spaces = Tiling.spaces;
let active = spaces.spaceOf(screen.get_active_workspace());
let [dx, dy] = event.get_scroll_delta();
dy *= active.height*0.05;
let t = event.get_time();
let v = -dy/(this.time - t);
// log(`v ${v}, dy: ${dy}`);
let firstEvent = false;
if (!this.selected) {
firstEvent = true;
this.selected = spaces.selectedSpace;
}
let transition = 'easeOutQuad';
if (dy > 0
&& this.selected !== active
&& ((this.selected.actor.y > 0.385*active.height &&
this.selected.actor.y - dy < 0.385*active.height)
||
(this.selected.actor.y - dy < 0.035*active.height))
) {
dy = 0;
v = 0.1;
spaces.selectSpace(Meta.MotionDirection.UP, false, transition);
this.selected = spaces.selectedSpace;
Tweener.removeTweens(this.selected.actor);
Tweener.addTween(this.selected.actor,
{scale_x: 0.9, scale_y: 0.9, time: 0.25, transition});
} else if (dy < 0
&& ((this.selected.actor.y < 0.60*active.height &&
this.selected.actor.y - dy > 0.60*active.height)
||
(this.selected.actor.y - dy > 0.95*active.height))
) {
dy = 0;
v = 0.1;
spaces.selectSpace(Meta.MotionDirection.DOWN, false, transition);
this.selected = spaces.selectedSpace;
Tweener.removeTweens(this.selected.actor);
Tweener.addTween(this.selected.actor,
{scale_x: 0.9, scale_y: 0.9, time: 0.25, transition});
}
this.selected.actor.y -= dy;
if (this.selected === active) {
let scale = 0.90;
let s = 1 - (1 - scale)*(this.selected.actor.y/(0.1*this.selected.height));
s = Math.max(s, scale);
Tweener.removeTweens(this.selected.actor);
this.selected.actor.set_scale(s, s);
}
if (v === 0 && !firstEvent) {
// log(`finish: ${this.velocity}`);
let test;
if (this.velocity > 0)
test = () => this.velocity > 0;
else
test = () => this.velocity < 0;
let y = this.selected.actor.y;
let friction = 0.5;
while (test()) {
let dy = this.velocity*16;
y -= dy;
// log(`calc target: ${dy} ${y} ${this.velocity}`);
if (this.velocity > 0)
this.velocity -= friction;
else
this.velocity += friction;
}
// log(`zero: ${y/this.selected.height}`);
if (this.selected === active && y <= 0.1*this.selected.height) {
this._navigator.finish();
return;
} else if (y > 0.6*this.selected.height) {
spaces.selectSpace(Meta.MotionDirection.DOWN, false, transition);
this.selected = spaces.selectedSpace;
} else {
spaces.selectSpace(Meta.MotionDirection.DOWN);
spaces.selectSpace(Meta.MotionDirection.UP);
}
} else {
this.time = t;
this.velocity = v;
}
}
return Clutter.EVENT_PROPAGATE;
}