[gnome-shell-extensions] nativeWindowPlacement: Use custom strategy to hook into layout



commit ef99394ffb779a115f26c65b69a7d84acdb1f3e5
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Sep 20 02:47:49 2017 +0200

    nativeWindowPlacement: Use custom strategy to hook into layout
    
    Instead of copying a long function for a single changed line, wrap the
    layout algorithm in a LayoutStrategy so the workspace code picks it
    up without modifications.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=787934

 extensions/native-window-placement/extension.js |  158 ++++-------------------
 1 files changed, 28 insertions(+), 130 deletions(-)
---
diff --git a/extensions/native-window-placement/extension.js b/extensions/native-window-placement/extension.js
index cce84aa..0796bf0 100644
--- a/extensions/native-window-placement/extension.js
+++ b/extensions/native-window-placement/extension.js
@@ -1,11 +1,7 @@
 // -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
 const Lang = imports.lang;
 
-const Overview = imports.ui.overview;
-const Tweener = imports.ui.tweener;
-
 const Workspace = imports.ui.workspace;
-const WindowPositionFlags = Workspace.WindowPositionFlags;
 
 const ExtensionUtils = imports.misc.extensionUtils;
 const Me = ExtensionUtils.getCurrentExtension();
@@ -78,39 +74,31 @@ const Rect = new Lang.Class({
     }
 });
 
-let winInjections, workspaceInjections, connectedSignals;
-
-function resetState() {
-    winInjections = { };
-    workspaceInjections = { };
-    connectedSignals = [ ];
-}
+const NaturalLayoutStrategy = new Lang.Class({
+    Name: 'NaturalLayoutStrategy',
+    Extends: Workspace.LayoutStrategy,
 
-function enable() {
-    resetState();
+    _init: function(settings) {
+        this._settings = settings;
+    },
 
-    let settings = Convenience.getSettings();
-    let useMoreScreen = settings.get_boolean('use-more-screen');
-    let signalId = settings.connect('changed::use-more-screen', function() {
-        useMoreScreen = settings.get_boolean('use-more-screen');
-    });
-    connectedSignals.push({ obj: settings, id: signalId });
+    computeLayout: function(windows, layout) {
+        layout.windows = windows;
+    },
 
     /**
-     * _calculateWindowTransformationsNatural:
-     * @clones: Array of #MetaWindow
-     *
      * Returns clones with matching target coordinates and scales to arrange windows in a natural way that 
no overlap exists and relative window size is preserved.
      * This function is almost a 1:1 copy of the function
      * PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
      * 
https://projects.kde.org/projects/kde/kdebase/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
      */
-    Workspace.Workspace.prototype._calculateWindowTransformationsNatural = function(clones, area) {
+    computeWindowSlots: function(layout, area) {
         // As we are using pseudo-random movement (See "slot") we need to make sure the list
         // is always sorted the same way no matter which window is currently active.
 
         let area_rect = new Rect(area.x, area.y, area.width, area.height);
         let bounds = area_rect.copy();
+        let clones = layout.windows;
 
         let direction = 0;
         let directions = [];
@@ -168,7 +156,7 @@ function enable() {
                         rects[j].translate(diff[0], diff[1]);
 
 
-                        if (useMoreScreen) {
+                        if (this._settings.get_boolean('use-more-screen')) {
                             // Try to keep the bounding rect the same aspect as the screen so that more
                             // screen real estate is utilised. We do this by splitting the screen into nine
                             // equal sections, if the window center is in any of the corner sections pull the
@@ -258,115 +246,28 @@ function enable() {
 
         return slots;
     }
-    workspaceInjections['_calculateWindowTransformationsNatural'] = undefined;
-
-    /**
-     * _updateWindowPositions:
-     * @flags:
-     *  INITIAL - this is the initial positioning of the windows.
-     *  ANIMATE - Indicates that we need animate changing position.
-     */
-    workspaceInjections['_updateWindowPositions'] = Workspace.Workspace.prototype._updateWindowPositions;
-    Workspace.Workspace.prototype._updateWindowPositions = function(flags) {
-            if (this._currentLayout == null) {
-                this._recalculateWindowPositions(flags);
-                return;
-            }
-
-            let initialPositioning = flags & WindowPositionFlags.INITIAL;
-            let animate = flags & WindowPositionFlags.ANIMATE;
-
-            let layout = this._currentLayout;
-            let strategy = layout.strategy;
-
-            let [, , padding] = this._getSpacingAndPadding();
-            let area = Workspace.padArea(this._actualGeometry, padding);
-
-            /// EDIT replace this version by our own:
-            //let slots = strategy.computeWindowSlots(layout, area);
-
-
-            /// EDIT copied from _realRecalculateWindowPositions:
-            let clones = this._windows.slice();
-            if (clones.length == 0)
-                return;
-
-            clones.sort(function(a, b) {
-                return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence();
-            });
-
-            if (this._reservedSlot)
-                clones.push(this._reservedSlot);
-
-            /// EDIT our own window placement function:
-            let slots = this._calculateWindowTransformationsNatural(clones, area);
-
-
-            let currentWorkspace = global.screen.get_active_workspace();
-            let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
-
-            for (let i = 0; i < slots.length; i++) {
-                let slot = slots[i];
-                let [x, y, scale, clone] = slot;
-                let metaWindow = clone.metaWindow;
-                let overlay = clone.overlay;
-                clone.slotId = i;
-
-                // Positioning a window currently being dragged must be avoided;
-                // we'll just leave a blank spot in the layout for it.
-                if (clone.inDrag)
-                    continue;
-
-                let cloneWidth = clone.actor.width * scale;
-                let cloneHeight = clone.actor.height * scale;
-                clone.slot = [x, y, cloneWidth, cloneHeight];
-
-                if (overlay && (initialPositioning || !clone.positioned))
-                    overlay.hide();
+});
 
-                if (!clone.positioned) {
-                    // This window appeared after the overview was already up
-                    // Grow the clone from the center of the slot
-                    clone.actor.x = x + cloneWidth / 2;
-                    clone.actor.y = y + cloneHeight / 2;
-                    clone.actor.scale_x = 0;
-                    clone.actor.scale_y = 0;
-                    clone.positioned = true;
-                }
+let winInjections, workspaceInjections;
 
-                if (animate && isOnCurrentWorkspace) {
-                    if (!metaWindow.showing_on_its_workspace()) {
-                        /* Hidden windows should fade in and grow
-                         * therefore we need to resize them now so they
-                         * can be scaled up later */
-                        if (initialPositioning) {
-                            clone.actor.opacity = 0;
-                            clone.actor.scale_x = 0;
-                            clone.actor.scale_y = 0;
-                            clone.actor.x = x;
-                            clone.actor.y = y;
-                        }
+function resetState() {
+    winInjections = { };
+    workspaceInjections = { };
+}
 
-                        Tweener.addTween(clone.actor,
-                                         { opacity: 255,
-                                           time: Overview.ANIMATION_TIME,
-                                           transition: 'easeInQuad'
-                                         });
-                    }
+function enable() {
+    resetState();
 
-                    this._animateClone(clone, overlay, x, y, scale, initialPositioning);
-                } else {
-                    // cancel any active tweens (otherwise they might override our changes)
-                    Tweener.removeTweens(clone.actor);
-                    clone.actor.set_position(x, y);
-                    clone.actor.set_scale(scale, scale);
-                    clone.overlay.relayout(false);
-                    this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
-                }
-            }
-        }
+    let settings = Convenience.getSettings();
 
+    workspaceInjections['_getBestLayout'] = Workspace.Workspace.prototype._getBestLayout;
+    Workspace.Workspace.prototype._getBestLayout = function(windows) {
+        let strategy = new NaturalLayoutStrategy(settings);
+        let layout = { strategy };
+        strategy.computeLayout(windows, layout);
 
+        return layout;
+    }
 
     /// position window titles on top of windows in overlay ////
     winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
@@ -395,9 +296,6 @@ function disable() {
     for (i in winInjections)
         removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
 
-    for each (i in connectedSignals)
-        i.obj.disconnect(i.id);
-
     global.stage.queue_relayout();
     resetState();
 }


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