[gnome-shell/wip/exalm/gestures: 63/63] workspaceAnimation: Support multiple screens



commit a7cf1fc1d8d8c8cd9ed312bff04144077799ddc9
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Thu Jul 4 23:43:23 2019 +0500

    workspaceAnimation: Support multiple screens
    
    Have a separate animating container on each screen, and sync their
    progress. Put each container into another actor, and clip it to that
    screen. Since WorkspaceGroup uses window clones now, windows that are
    visible on multiple screens at once would look and animate correctly.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1213
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605

 js/ui/workspaceAnimation.js | 163 ++++++++++++++++++++++++++++----------------
 1 file changed, 103 insertions(+), 60 deletions(-)
---
diff --git a/js/ui/workspaceAnimation.js b/js/ui/workspaceAnimation.js
index b0a52a05b0..6e77e3be49 100644
--- a/js/ui/workspaceAnimation.js
+++ b/js/ui/workspaceAnimation.js
@@ -10,11 +10,12 @@ const WINDOW_ANIMATION_TIME = 250;
 
 const WorkspaceGroup = GObject.registerClass(
 class WorkspaceGroup extends Clutter.Actor {
-    _init(controller, workspace) {
+    _init(controller, workspace, monitor) {
         super._init();
 
         this._controller = controller;
         this._workspace = workspace;
+        this._monitor = monitor;
         this._windows = [];
 
         this._refreshWindows();
@@ -28,6 +29,10 @@ class WorkspaceGroup extends Clutter.Actor {
         if (window.get_workspace() !== this._workspace)
             return false;
 
+        let geometry = global.display.get_monitor_geometry(this._monitor.index);
+        if (!window.get_frame_rect().intersect(geometry)[0])
+            return false;
+
         if (!window.showing_on_its_workspace())
             return false;
 
@@ -105,45 +110,60 @@ const WorkspaceAnimation = GObject.registerClass({
 
         this._controller = controller;
         this._movingWindow = null;
-        this._surroundings = {};
+        this._monitors = [];
         this._progress = 0;
 
-        this._container = new Clutter.Actor();
-
-        this.add_actor(this._container);
         global.window_group.add_actor(this);
 
         let workspaceManager = global.workspace_manager;
         let curWs = workspaceManager.get_workspace_by_index(from);
 
-        this._curGroup = new WorkspaceGroup(controller, curWs);
-        this._container.add_actor(this._curGroup);
-
-        for (let dir of Object.values(Meta.MotionDirection)) {
-            let ws = null;
-
-            if (to < 0)
-                ws = curWs.get_neighbor(dir);
-            else if (dir === direction)
-                ws = workspaceManager.get_workspace_by_index(to);
+        for (let monitor of Main.layoutManager.monitors) {
+            let record = {
+                index: monitor.index,
+                clipBin: new Clutter.Actor(),
+                container: new Clutter.Actor(),
+                surroundings: {},
+            };
 
-            if (ws === null || ws === curWs) {
-                this._surroundings[dir] = null;
-                continue;
+            record.clipBin.add_actor(record.container);
+            record.clipBin.set_clip(monitor.x, monitor.y, monitor.width,
+                monitor.height);
+
+            this.add_actor(record.clipBin);
+
+            record.curGroup = new WorkspaceGroup(controller, curWs, monitor);
+            record.container.add_actor(record.curGroup);
+
+            for (let dir of Object.values(Meta.MotionDirection)) {
+                let ws = null;
+
+                if (to < 0)
+                    ws = curWs.get_neighbor(dir);
+                else if (dir === direction)
+                    ws = workspaceManager.get_workspace_by_index(to);
+
+                if (ws === null || ws === curWs) {
+                    record.surroundings[dir] = null;
+                    continue;
+                }
+
+                let [x, y] = this._getPositionForDirection(dir, curWs, ws,
+                    monitor.index);
+                let info = {
+                    index: ws.index(),
+                    actor: new WorkspaceGroup(controller, ws, monitor),
+                    xDest: x,
+                    yDest: y,
+                };
+                record.surroundings[dir] = info;
+                record.container.add_actor(info.actor);
+                record.container.set_child_above_sibling(info.actor, null);
+
+                info.actor.set_position(x, y);
             }
 
-            let [x, y] = this._getPositionForDirection(dir, curWs, ws);
-            let info = {
-                index: ws.index(),
-                actor: new WorkspaceGroup(controller, ws),
-                xDest: x,
-                yDest: y,
-            };
-            this._surroundings[dir] = info;
-            this._container.add_actor(info.actor);
-            this._container.set_child_above_sibling(info.actor, null);
-
-            info.actor.set_position(x, y);
+            this._monitors.push(record);
         }
 
         if (this._controller.movingWindow) {
@@ -170,6 +190,10 @@ const WorkspaceAnimation = GObject.registerClass({
     _onDestroy() {
         this.remove_all_transitions();
 
+        for (let monitorData of this._monitors)
+            monitorData.clipBin.destroy();
+        this._monitors = [];
+
         if (this._movingWindow) {
             let record = this._movingWindow;
             record.window.disconnect(record.windowDestroyId);
@@ -179,38 +203,41 @@ const WorkspaceAnimation = GObject.registerClass({
 
             this._movingWindow = null;
         }
-
-        this._container.destroy();
     }
 
-    _getPositionForDirection(direction, fromWs, toWs) {
+    _getPositionForDirection(direction, fromWs, toWs, monitor) {
         let xDest = 0, yDest = 0;
 
-        let oldWsIsFullscreen = fromWs.list_windows().some(w => w.is_fullscreen());
-        let newWsIsFullscreen = toWs.list_windows().some(w => w.is_fullscreen());
+        let condition = w => w.get_monitor() === monitor && w.is_fullscreen();
+
+        let oldWsIsFullscreen = fromWs.list_windows().some(condition);
+        let newWsIsFullscreen = toWs.list_windows().some(condition);
+
+        let geometry = Main.layoutManager.monitors[monitor];
 
         // 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.
-        let shiftHeight = Main.panel.height;
+        let shiftHeight = monitor === Main.layoutManager.primaryIndex
+            ? Main.panel.height : 0;
 
         if (direction === Meta.MotionDirection.UP ||
             direction === Meta.MotionDirection.UP_LEFT ||
             direction === Meta.MotionDirection.UP_RIGHT)
-            yDest = -global.screen_height + (oldWsIsFullscreen ? 0 : shiftHeight);
+            yDest = -geometry.height + (oldWsIsFullscreen ? 0 : shiftHeight);
         else if (direction === Meta.MotionDirection.DOWN ||
             direction === Meta.MotionDirection.DOWN_LEFT ||
             direction === Meta.MotionDirection.DOWN_RIGHT)
-            yDest = global.screen_height - (newWsIsFullscreen ? 0 : shiftHeight);
+            yDest = geometry.height - (newWsIsFullscreen ? 0 : shiftHeight);
 
         if (direction === Meta.MotionDirection.LEFT ||
             direction === Meta.MotionDirection.UP_LEFT ||
             direction === Meta.MotionDirection.DOWN_LEFT)
-            xDest = -global.screen_width;
+            xDest = -geometry.width;
         else if (direction === Meta.MotionDirection.RIGHT ||
                  direction === Meta.MotionDirection.UP_RIGHT ||
                  direction === Meta.MotionDirection.DOWN_RIGHT)
-            xDest = global.screen_width;
+            xDest = geometry.width;
 
         return [xDest, yDest];
     }
@@ -248,21 +275,24 @@ const WorkspaceAnimation = GObject.registerClass({
         this._progress = progress;
 
         let direction = this.directionForProgress(progress);
-        let xPos = 0;
-        let yPos = 0;
 
-        if (global.workspace_manager.layout_rows === -1)
-            yPos = -Math.round(progress * this._getDistance(direction));
-        else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
-            xPos = Math.round(progress * this._getDistance(direction));
-        else
-            xPos = -Math.round(progress * this._getDistance(direction));
+        for (let monitorData of this._monitors) {
+            let xPos = 0;
+            let yPos = 0;
+
+            if (global.workspace_manager.layout_rows === -1)
+                yPos = -Math.round(progress * this._getDistance(monitorData, direction));
+            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
+                xPos = Math.round(progress * this._getDistance(monitorData, direction));
+            else
+                xPos = -Math.round(progress * this._getDistance(monitorData, direction));
 
-        this._container.set_position(xPos, yPos);
+            monitorData.container.set_position(xPos, yPos);
+        }
     }
 
-    _getDistance(direction) {
-        let info = this._surroundings[direction];
+    _getDistance(monitorData, direction) {
+        let info = monitorData.surroundings[direction];
         if (!info)
             return 0;
 
@@ -280,19 +310,30 @@ const WorkspaceAnimation = GObject.registerClass({
         return 0;
     }
 
-    getProgressRange() {
+    getProgressRange(monitor) {
+        let monitorData = null;
+        for (let data of this._monitors) {
+            if (data.index === monitor) {
+                monitorData = data;
+                break;
+            }
+        }
+
+        if (!monitorData)
+            return 0;
+
         let baseDistance;
         if (global.workspace_manager.layout_rows !== -1)
-            baseDistance = global.screen_width;
+            baseDistance = Main.layoutManager.monitors[monitor].width;
         else
-            baseDistance = global.screen_height;
+            baseDistance = Main.layoutManager.monitors[monitor].height;
 
         let direction = this.directionForProgress(-1);
-        let distance = this._getDistance(direction);
+        let distance = this._getDistance(monitorData, direction);
         let lower = -distance / baseDistance;
 
         direction = this.directionForProgress(1);
-        distance = this._getDistance(direction);
+        distance = this._getDistance(monitorData, direction);
         let upper = distance / baseDistance;
 
         return [lower, upper];
@@ -339,6 +380,7 @@ var WorkspaceAnimationController = class {
         this._inProgress = false;
         this._gestureActivated = false;
         this.movingWindow = null;
+        this._monitor = null;
     }
 
     animateSwitchWorkspace(from, to, direction, onComplete) {
@@ -372,9 +414,9 @@ var WorkspaceAnimationController = class {
 
         let baseDistance;
         if (horiz)
-            baseDistance = global.screen_width;
+            baseDistance = Main.layoutManager.monitors[monitor].width;
         else
-            baseDistance = global.screen_height;
+            baseDistance = Main.layoutManager.monitors[monitor].height;
 
         let progress;
         if (this._gestureActivated) {
@@ -385,7 +427,8 @@ var WorkspaceAnimationController = class {
             progress = 0;
         }
 
-        let [lower, upper] = this._animation.getProgressRange();
+        this._monitor = monitor;
+        let [lower, upper] = this._animation.getProgressRange(monitor);
         if (progress < 0)
             progress *= -lower;
         else if (progress > 0)
@@ -405,7 +448,7 @@ var WorkspaceAnimationController = class {
 
     _switchWorkspaceUpdate(tracker, progress) {
         // Translate the progress into [-1;1] range
-        let [lower, upper] = this._animation.getProgressRange();
+        let [lower, upper] = this._animation.getProgressRange(this._monitor);
         if (progress < 0)
             progress /= -lower;
         else if (progress > 0)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]