2019-07-02 17:28:47 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2021-12-18 23:05:21 +00:00
|
|
|
/* exported WorkspaceAnimationController, WorkspaceGroup */
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 20:29:21 +00:00
|
|
|
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-07-16 10:40:13 +00:00
|
|
|
const Background = imports.ui.background;
|
|
|
|
const Layout = imports.ui.layout;
|
2019-07-02 17:28:47 +00:00
|
|
|
const Main = imports.ui.main;
|
|
|
|
const SwipeTracker = imports.ui.swipeTracker;
|
|
|
|
|
|
|
|
const WINDOW_ANIMATION_TIME = 250;
|
2020-06-20 20:29:21 +00:00
|
|
|
const WORKSPACE_SPACING = 100;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2021-12-18 23:05:21 +00:00
|
|
|
var WorkspaceGroup = GObject.registerClass(
|
2019-07-04 17:44:15 +00:00
|
|
|
class WorkspaceGroup extends Clutter.Actor {
|
2020-06-20 19:43:06 +00:00
|
|
|
_init(workspace, monitor, movingWindow) {
|
2019-07-04 17:44:15 +00:00
|
|
|
super._init();
|
|
|
|
|
|
|
|
this._workspace = workspace;
|
2020-06-20 19:43:06 +00:00
|
|
|
this._monitor = monitor;
|
2019-07-04 17:44:15 +00:00
|
|
|
this._movingWindow = movingWindow;
|
|
|
|
this._windowRecords = [];
|
|
|
|
|
2020-06-20 20:29:21 +00:00
|
|
|
if (this._workspace) {
|
|
|
|
this._background = new Meta.BackgroundGroup();
|
|
|
|
|
|
|
|
this.add_actor(this._background);
|
|
|
|
|
|
|
|
this._bgManager = new Background.BackgroundManager({
|
|
|
|
container: this._background,
|
|
|
|
monitorIndex: this._monitor.index,
|
|
|
|
controlPosition: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.width = monitor.width;
|
|
|
|
this.height = monitor.height;
|
|
|
|
this.clip_to_allocation = true;
|
|
|
|
|
2019-07-04 17:44:15 +00:00
|
|
|
this._createWindows();
|
|
|
|
|
|
|
|
this.connect('destroy', this._onDestroy.bind(this));
|
|
|
|
this._restackedId = global.display.connect('restacked',
|
|
|
|
this._syncStacking.bind(this));
|
|
|
|
}
|
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
get workspace() {
|
|
|
|
return this._workspace;
|
|
|
|
}
|
|
|
|
|
2019-07-04 17:44:15 +00:00
|
|
|
_shouldShowWindow(window) {
|
|
|
|
if (!window.showing_on_its_workspace())
|
|
|
|
return false;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const geometry = global.display.get_monitor_geometry(this._monitor.index);
|
|
|
|
const [intersects] = window.get_frame_rect().intersect(geometry);
|
|
|
|
if (!intersects)
|
|
|
|
return false;
|
|
|
|
|
2019-07-04 17:44:15 +00:00
|
|
|
const isSticky =
|
|
|
|
window.is_on_all_workspaces() || window === this._movingWindow;
|
|
|
|
|
2020-06-20 18:44:24 +00:00
|
|
|
// No workspace means we should show windows that are on all workspaces
|
|
|
|
if (!this._workspace)
|
|
|
|
return isSticky;
|
|
|
|
|
|
|
|
// Otherwise only show windows that are (only) on that workspace
|
2019-07-04 17:44:15 +00:00
|
|
|
return !isSticky && window.located_on_workspace(this._workspace);
|
|
|
|
}
|
|
|
|
|
|
|
|
_syncStacking() {
|
2019-07-04 18:15:15 +00:00
|
|
|
const windowActors = global.get_window_actors().filter(w =>
|
|
|
|
this._shouldShowWindow(w.meta_window));
|
|
|
|
|
|
|
|
let lastRecord;
|
2019-07-04 17:44:15 +00:00
|
|
|
|
|
|
|
for (const windowActor of windowActors) {
|
2019-07-04 18:15:15 +00:00
|
|
|
const record = this._windowRecords.find(r => r.windowActor === windowActor);
|
|
|
|
|
2020-06-20 20:29:21 +00:00
|
|
|
this.set_child_above_sibling(record.clone, lastRecord ? lastRecord.clone : this._background);
|
2019-07-04 18:15:15 +00:00
|
|
|
lastRecord = record;
|
2019-07-04 17:44:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_createWindows() {
|
|
|
|
const windowActors = global.get_window_actors().filter(w =>
|
|
|
|
this._shouldShowWindow(w.meta_window));
|
|
|
|
|
|
|
|
for (const windowActor of windowActors) {
|
2019-07-04 18:15:15 +00:00
|
|
|
const clone = new Clutter.Clone({
|
|
|
|
source: windowActor,
|
2020-06-20 19:43:06 +00:00
|
|
|
x: windowActor.x - this._monitor.x,
|
|
|
|
y: windowActor.y - this._monitor.y,
|
2019-07-04 18:15:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this.add_child(clone);
|
2019-07-04 17:44:15 +00:00
|
|
|
|
2019-07-04 18:15:15 +00:00
|
|
|
const record = { windowActor, clone };
|
2019-07-04 17:44:15 +00:00
|
|
|
|
|
|
|
record.windowDestroyId = windowActor.connect('destroy', () => {
|
2019-07-04 18:15:15 +00:00
|
|
|
clone.destroy();
|
2019-07-04 17:44:15 +00:00
|
|
|
this._windowRecords.splice(this._windowRecords.indexOf(record), 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
this._windowRecords.push(record);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_removeWindows() {
|
|
|
|
for (const record of this._windowRecords) {
|
|
|
|
record.windowActor.disconnect(record.windowDestroyId);
|
2019-07-04 18:15:15 +00:00
|
|
|
record.clone.destroy();
|
2019-07-04 17:44:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this._windowRecords = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
_onDestroy() {
|
|
|
|
global.display.disconnect(this._restackedId);
|
|
|
|
this._removeWindows();
|
2020-06-20 20:29:21 +00:00
|
|
|
|
|
|
|
if (this._workspace)
|
|
|
|
this._bgManager.destroy();
|
2019-07-04 17:44:15 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const MonitorGroup = GObject.registerClass({
|
|
|
|
Properties: {
|
|
|
|
'progress': GObject.ParamSpec.double(
|
|
|
|
'progress', 'progress', 'progress',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
|
|
|
-Infinity, Infinity, 0),
|
|
|
|
},
|
2020-06-20 20:29:21 +00:00
|
|
|
}, class MonitorGroup extends St.Widget {
|
2020-06-20 19:43:06 +00:00
|
|
|
_init(monitor, workspaceIndices, movingWindow) {
|
|
|
|
super._init({
|
|
|
|
clip_to_allocation: true,
|
2020-06-20 20:29:21 +00:00
|
|
|
style_class: 'workspace-animation',
|
2020-06-20 19:43:06 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this._monitor = monitor;
|
2020-07-16 10:40:13 +00:00
|
|
|
|
|
|
|
const constraint = new Layout.MonitorConstraint({ index: monitor.index });
|
|
|
|
this.add_constraint(constraint);
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
this._container = new Clutter.Actor();
|
|
|
|
this.add_child(this._container);
|
|
|
|
|
|
|
|
const stickyGroup = new WorkspaceGroup(null, monitor, movingWindow);
|
|
|
|
this.add_child(stickyGroup);
|
|
|
|
|
|
|
|
this._workspaceGroups = [];
|
|
|
|
|
|
|
|
const workspaceManager = global.workspace_manager;
|
|
|
|
const vertical = workspaceManager.layout_rows === -1;
|
|
|
|
const activeWorkspace = workspaceManager.get_active_workspace();
|
|
|
|
|
|
|
|
let x = 0;
|
|
|
|
let y = 0;
|
|
|
|
|
|
|
|
for (const i of workspaceIndices) {
|
|
|
|
const ws = workspaceManager.get_workspace_by_index(i);
|
|
|
|
const fullscreen = ws.list_windows().some(w => w.get_monitor() === monitor.index && w.is_fullscreen());
|
|
|
|
|
|
|
|
if (i > 0 && vertical && !fullscreen && monitor.index === Main.layoutManager.primaryIndex) {
|
|
|
|
// We have to shift windows up or down by the height of the panel to prevent having a
|
|
|
|
// visible gap between the windows while switching workspaces. Since fullscreen windows
|
|
|
|
// hide the panel, they don't need to be shifted up or down.
|
|
|
|
y -= Main.panel.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
const group = new WorkspaceGroup(ws, monitor, movingWindow);
|
|
|
|
|
|
|
|
this._workspaceGroups.push(group);
|
|
|
|
this._container.add_child(group);
|
|
|
|
group.set_position(x, y);
|
|
|
|
|
|
|
|
if (vertical)
|
|
|
|
y += this.baseDistance;
|
|
|
|
else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
|
|
|
|
x -= this.baseDistance;
|
|
|
|
else
|
|
|
|
x += this.baseDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.progress = this.getWorkspaceProgress(activeWorkspace);
|
2020-07-16 10:40:13 +00:00
|
|
|
}
|
2020-06-20 19:43:06 +00:00
|
|
|
|
|
|
|
get baseDistance() {
|
2020-06-20 20:29:21 +00:00
|
|
|
const spacing = WORKSPACE_SPACING * St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
if (global.workspace_manager.layout_rows === -1)
|
2020-06-20 20:29:21 +00:00
|
|
|
return this._monitor.height + spacing;
|
2020-06-20 19:43:06 +00:00
|
|
|
else
|
2020-06-20 20:29:21 +00:00
|
|
|
return this._monitor.width + spacing;
|
2020-06-20 19:43:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get progress() {
|
|
|
|
if (global.workspace_manager.layout_rows === -1)
|
|
|
|
return -this._container.y / this.baseDistance;
|
|
|
|
else if (this.get_text_direction() === Clutter.TextDirection.RTL)
|
|
|
|
return this._container.x / this.baseDistance;
|
|
|
|
else
|
|
|
|
return -this._container.x / this.baseDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
set progress(p) {
|
|
|
|
if (global.workspace_manager.layout_rows === -1)
|
|
|
|
this._container.y = -Math.round(p * this.baseDistance);
|
|
|
|
else if (this.get_text_direction() === Clutter.TextDirection.RTL)
|
|
|
|
this._container.x = Math.round(p * this.baseDistance);
|
|
|
|
else
|
|
|
|
this._container.x = -Math.round(p * this.baseDistance);
|
|
|
|
}
|
|
|
|
|
|
|
|
get index() {
|
|
|
|
return this._monitor.index;
|
|
|
|
}
|
|
|
|
|
|
|
|
getWorkspaceProgress(workspace) {
|
|
|
|
const group = this._workspaceGroups.find(g =>
|
|
|
|
g.workspace.index() === workspace.index());
|
|
|
|
return this._getWorkspaceGroupProgress(group);
|
|
|
|
}
|
|
|
|
|
|
|
|
_getWorkspaceGroupProgress(group) {
|
|
|
|
if (global.workspace_manager.layout_rows === -1)
|
|
|
|
return group.y / this.baseDistance;
|
|
|
|
else if (this.get_text_direction() === Clutter.TextDirection.RTL)
|
|
|
|
return -group.x / this.baseDistance;
|
|
|
|
else
|
|
|
|
return group.x / this.baseDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
getSnapPoints() {
|
|
|
|
return this._workspaceGroups.map(g =>
|
|
|
|
this._getWorkspaceGroupProgress(g));
|
|
|
|
}
|
|
|
|
|
|
|
|
findClosestWorkspace(progress) {
|
|
|
|
const distances = this.getSnapPoints().map(p =>
|
|
|
|
Math.abs(p - progress));
|
|
|
|
const index = distances.indexOf(Math.min(...distances));
|
|
|
|
return this._workspaceGroups[index].workspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
_interpolateProgress(progress, monitorGroup) {
|
|
|
|
if (this.index === monitorGroup.index)
|
|
|
|
return progress;
|
|
|
|
|
|
|
|
const points1 = monitorGroup.getSnapPoints();
|
|
|
|
const points2 = this.getSnapPoints();
|
|
|
|
|
|
|
|
const upper = points1.indexOf(points1.find(p => p >= progress));
|
|
|
|
const lower = points1.indexOf(points1.slice().reverse().find(p => p <= progress));
|
|
|
|
|
|
|
|
if (points1[upper] === points1[lower])
|
|
|
|
return points2[upper];
|
|
|
|
|
|
|
|
const t = (progress - points1[lower]) / (points1[upper] - points1[lower]);
|
|
|
|
|
|
|
|
return points2[lower] + (points2[upper] - points2[lower]) * t;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSwipeForMonitor(progress, monitorGroup) {
|
|
|
|
this.progress = this._interpolateProgress(progress, monitorGroup);
|
|
|
|
}
|
2020-07-16 10:40:13 +00:00
|
|
|
});
|
|
|
|
|
2019-07-02 17:28:47 +00:00
|
|
|
var WorkspaceAnimationController = class {
|
|
|
|
constructor() {
|
|
|
|
this._movingWindow = null;
|
|
|
|
this._switchData = null;
|
|
|
|
|
|
|
|
Main.overview.connect('showing', () => {
|
|
|
|
if (this._switchData) {
|
|
|
|
if (this._switchData.gestureActivated)
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
this._finishWorkspaceSwitch(this._switchData);
|
2019-07-02 17:28:47 +00:00
|
|
|
this._swipeTracker.enabled = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Main.overview.connect('hiding', () => {
|
|
|
|
this._swipeTracker.enabled = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
const swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
|
2021-03-01 16:53:55 +00:00
|
|
|
Clutter.Orientation.HORIZONTAL,
|
|
|
|
Shell.ActionMode.NORMAL,
|
|
|
|
{ allowDrag: false });
|
2019-07-02 17:28:47 +00:00
|
|
|
swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
|
|
|
|
swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
|
|
|
|
swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
|
|
|
|
this._swipeTracker = swipeTracker;
|
2021-01-29 19:33:23 +00:00
|
|
|
|
|
|
|
global.display.bind_property('compositor-modifiers',
|
|
|
|
this._swipeTracker, 'scroll-modifiers',
|
|
|
|
GObject.BindingFlags.SYNC_CREATE);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
_prepareWorkspaceSwitch(workspaceIndices) {
|
2019-07-02 17:28:47 +00:00
|
|
|
if (this._switchData)
|
|
|
|
return;
|
|
|
|
|
2019-07-04 17:44:15 +00:00
|
|
|
const workspaceManager = global.workspace_manager;
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
const nWorkspaces = workspaceManager.get_n_workspaces();
|
2019-07-04 17:44:15 +00:00
|
|
|
|
2019-07-02 17:28:47 +00:00
|
|
|
const switchData = {};
|
|
|
|
|
|
|
|
this._switchData = switchData;
|
2020-06-20 19:43:06 +00:00
|
|
|
switchData.monitors = [];
|
|
|
|
|
2019-07-02 17:28:47 +00:00
|
|
|
switchData.gestureActivated = false;
|
|
|
|
switchData.inProgress = false;
|
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
if (!workspaceIndices)
|
|
|
|
workspaceIndices = [...Array(nWorkspaces).keys()];
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const monitors = Meta.prefs_get_workspaces_only_on_primary()
|
|
|
|
? [Main.layoutManager.primaryMonitor] : Main.layoutManager.monitors;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
for (const monitor of monitors) {
|
|
|
|
if (Meta.prefs_get_workspaces_only_on_primary() &&
|
|
|
|
monitor.index !== Main.layoutManager.primaryIndex)
|
|
|
|
continue;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const group = new MonitorGroup(monitor, workspaceIndices, this.movingWindow);
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
Main.uiGroup.insert_child_above(group, global.window_group);
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
switchData.monitors.push(group);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
2021-01-09 12:43:14 +00:00
|
|
|
|
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_finishWorkspaceSwitch(switchData) {
|
2021-01-09 12:43:14 +00:00
|
|
|
Meta.enable_unredirect_for_display(global.display);
|
|
|
|
|
2019-07-02 17:28:47 +00:00
|
|
|
this._switchData = null;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
switchData.monitors.forEach(m => m.destroy());
|
2019-07-02 17:28:47 +00:00
|
|
|
|
|
|
|
this.movingWindow = null;
|
|
|
|
}
|
|
|
|
|
2020-01-21 13:09:56 +00:00
|
|
|
animateSwitch(from, to, direction, onComplete) {
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
this._swipeTracker.enabled = false;
|
|
|
|
|
|
|
|
let workspaceIndices = [];
|
|
|
|
|
|
|
|
switch (direction) {
|
|
|
|
case Meta.MotionDirection.UP:
|
|
|
|
case Meta.MotionDirection.LEFT:
|
|
|
|
case Meta.MotionDirection.UP_LEFT:
|
|
|
|
case Meta.MotionDirection.UP_RIGHT:
|
|
|
|
workspaceIndices = [to, from];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Meta.MotionDirection.DOWN:
|
|
|
|
case Meta.MotionDirection.RIGHT:
|
|
|
|
case Meta.MotionDirection.DOWN_LEFT:
|
|
|
|
case Meta.MotionDirection.DOWN_RIGHT:
|
|
|
|
workspaceIndices = [from, to];
|
|
|
|
break;
|
|
|
|
}
|
2019-07-02 17:28:47 +00:00
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL &&
|
|
|
|
direction !== Meta.MotionDirection.UP &&
|
|
|
|
direction !== Meta.MotionDirection.DOWN)
|
|
|
|
workspaceIndices.reverse();
|
2019-07-02 17:28:47 +00:00
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
this._prepareWorkspaceSwitch(workspaceIndices);
|
|
|
|
this._switchData.inProgress = true;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const fromWs = global.workspace_manager.get_workspace_by_index(from);
|
|
|
|
const toWs = global.workspace_manager.get_workspace_by_index(to);
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
for (const monitorGroup of this._switchData.monitors) {
|
|
|
|
monitorGroup.progress = monitorGroup.getWorkspaceProgress(fromWs);
|
|
|
|
const progress = monitorGroup.getWorkspaceProgress(toWs);
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
duration: WINDOW_ANIMATION_TIME,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (monitorGroup.index === Main.layoutManager.primaryIndex) {
|
|
|
|
params.onComplete = () => {
|
|
|
|
this._finishWorkspaceSwitch(this._switchData);
|
|
|
|
onComplete();
|
|
|
|
this._swipeTracker.enabled = true;
|
|
|
|
};
|
|
|
|
}
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
monitorGroup.ease_property('progress', progress, params);
|
|
|
|
}
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
}
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2021-01-29 19:33:23 +00:00
|
|
|
canHandleScrollEvent(event) {
|
|
|
|
return this._swipeTracker.canHandleScrollEvent(event);
|
|
|
|
}
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
_findMonitorGroup(monitorIndex) {
|
|
|
|
return this._switchData.monitors.find(m => m.index === monitorIndex);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_switchWorkspaceBegin(tracker, monitor) {
|
|
|
|
if (Meta.prefs_get_workspaces_only_on_primary() &&
|
|
|
|
monitor !== Main.layoutManager.primaryIndex)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const workspaceManager = global.workspace_manager;
|
|
|
|
const horiz = workspaceManager.layout_rows !== -1;
|
|
|
|
tracker.orientation = horiz
|
|
|
|
? Clutter.Orientation.HORIZONTAL
|
|
|
|
: Clutter.Orientation.VERTICAL;
|
|
|
|
|
|
|
|
if (this._switchData && this._switchData.gestureActivated) {
|
2020-06-20 19:43:06 +00:00
|
|
|
for (const group of this._switchData.monitors)
|
|
|
|
group.remove_all_transitions();
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
} else {
|
|
|
|
this._prepareWorkspaceSwitch();
|
2020-06-20 19:43:06 +00:00
|
|
|
}
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const monitorGroup = this._findMonitorGroup(monitor);
|
|
|
|
const baseDistance = monitorGroup.baseDistance;
|
|
|
|
const progress = monitorGroup.progress;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const closestWs = monitorGroup.findClosestWorkspace(progress);
|
|
|
|
const cancelProgress = monitorGroup.getWorkspaceProgress(closestWs);
|
|
|
|
const points = monitorGroup.getSnapPoints();
|
2019-07-02 17:28:47 +00:00
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
this._switchData.baseMonitorGroup = monitorGroup;
|
2019-07-02 17:28:47 +00:00
|
|
|
|
workspaceAnimation: Use a workspace strip
Currently, the workspace swipe transition only has one workspace in each
direction. This works until you try to do multiple swipes in quick
succession. The second swipe would continue the existing transition, which
only has 2 or 3 workspaces in it, and will hit a wall.
To prevent this, take all workspaces and arrange them into a column or row,
depending on the layout, and use that as a transition.
For the transition that happens when focusing a window on another workspace
(for example, via Alt+Tab), still use only two workspaces instead of all of
them.
Since we don't support layouts other than single rows/columns anymore,
diagonal transitions aren't supported anymore, and will be shown as
horizontal or vertical instead.
Since nw alt-tab and gesture transitions are different, don't allow to do
both at once, that is, disable swipe tracker when a programmatic transition
is going. This will also conveniently cancel a gesture transition if a
programmatic one is initiated while a gesture is in progress.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2612
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326>
2020-06-20 17:01:25 +00:00
|
|
|
tracker.confirmSwipe(baseDistance, points, progress, cancelProgress);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_switchWorkspaceUpdate(tracker, progress) {
|
|
|
|
if (!this._switchData)
|
|
|
|
return;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
for (const monitorGroup of this._switchData.monitors)
|
|
|
|
monitorGroup.updateSwipeForMonitor(progress, this._switchData.baseMonitorGroup);
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_switchWorkspaceEnd(tracker, duration, endProgress) {
|
|
|
|
if (!this._switchData)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const switchData = this._switchData;
|
|
|
|
switchData.gestureActivated = true;
|
|
|
|
|
2020-06-20 19:43:06 +00:00
|
|
|
const newWs = switchData.baseMonitorGroup.findClosestWorkspace(endProgress);
|
|
|
|
|
|
|
|
for (const monitorGroup of this._switchData.monitors) {
|
|
|
|
const progress = monitorGroup.getWorkspaceProgress(newWs);
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
duration,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (monitorGroup.index === Main.layoutManager.primaryIndex) {
|
|
|
|
params.onComplete = () => {
|
|
|
|
if (!newWs.active)
|
|
|
|
newWs.activate(global.get_current_time());
|
|
|
|
this._finishWorkspaceSwitch(switchData);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
monitorGroup.ease_property('progress', progress, params);
|
|
|
|
}
|
2019-07-02 17:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get gestureActive() {
|
|
|
|
return this._switchData !== null && this._switchData.gestureActivated;
|
|
|
|
}
|
|
|
|
|
2020-01-21 13:09:56 +00:00
|
|
|
cancelSwitchAnimation() {
|
|
|
|
if (!this._switchData)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (this._switchData.gestureActivated)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._finishWorkspaceSwitch(this._switchData);
|
|
|
|
}
|
|
|
|
|
2019-07-02 17:28:47 +00:00
|
|
|
set movingWindow(movingWindow) {
|
|
|
|
this._movingWindow = movingWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
get movingWindow() {
|
|
|
|
return this._movingWindow;
|
|
|
|
}
|
|
|
|
};
|