Compare commits
	
		
			36 Commits
		
	
	
		
			wip/lockdo
			...
			gbsneto/ic
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					87a76a5757 | ||
| 
						 | 
					717ec0f8a4 | ||
| 
						 | 
					854922866b | ||
| 
						 | 
					40ad9ab18c | ||
| 
						 | 
					55eb949def | ||
| 
						 | 
					0596848c27 | ||
| 
						 | 
					0bdcf2958f | ||
| 
						 | 
					ac3bc03f3f | ||
| 
						 | 
					bf322cd51a | ||
| 
						 | 
					6e3696baad | ||
| 
						 | 
					4056c56800 | ||
| 
						 | 
					ebf2610140 | ||
| 
						 | 
					a9e7b7853a | ||
| 
						 | 
					0dd430f2f4 | ||
| 
						 | 
					ca01b0287e | ||
| 
						 | 
					37aa5d0faf | ||
| 
						 | 
					2e4fb404a7 | ||
| 
						 | 
					11ce7829bc | ||
| 
						 | 
					52257f5137 | ||
| 
						 | 
					74077b0f6e | ||
| 
						 | 
					241b4cd1c8 | ||
| 
						 | 
					79f9391c00 | ||
| 
						 | 
					6da23c8d4d | ||
| 
						 | 
					bb9f05843f | ||
| 
						 | 
					cc9f949b65 | ||
| 
						 | 
					23191ec239 | ||
| 
						 | 
					038917e5f1 | ||
| 
						 | 
					f214c5b572 | ||
| 
						 | 
					9da49606f7 | ||
| 
						 | 
					c13efe96dc | ||
| 
						 | 
					47d2f4dbeb | ||
| 
						 | 
					48a2b6cb0b | ||
| 
						 | 
					ce78e8ae54 | ||
| 
						 | 
					abe9b82c48 | ||
| 
						 | 
					6c85bd6aeb | ||
| 
						 | 
					06a7ab871f | 
@@ -109,6 +109,10 @@
 | 
			
		||||
        the shell.
 | 
			
		||||
      </description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="icons-data" type="a{sv}">
 | 
			
		||||
      <default>[]</default>
 | 
			
		||||
      <summary>Data about the icons in the icon grid</summary>
 | 
			
		||||
    </key>
 | 
			
		||||
    <child name="keybindings" schema="org.gnome.shell.keybindings"/>
 | 
			
		||||
  </schema>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1514,6 +1514,9 @@ StScrollBar {
 | 
			
		||||
      border-image: none;
 | 
			
		||||
      background-image: none;
 | 
			
		||||
    }
 | 
			
		||||
    &:drop .overview-icon {
 | 
			
		||||
      background-color: transparentize($selected_bg_color,.15);
 | 
			
		||||
    }
 | 
			
		||||
    &:active .overview-icon,
 | 
			
		||||
    &:checked .overview-icon {
 | 
			
		||||
      background-color: transparentize(darken($osd_bg_color,10%), 0.5);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1161
									
								
								js/ui/appDisplay.js
									
									
									
									
									
								
							
							
						
						
									
										1161
									
								
								js/ui/appDisplay.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -25,6 +25,32 @@ function getAppFromSource(source) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
 | 
			
		||||
    constructor(app) {
 | 
			
		||||
        super(app, null, {
 | 
			
		||||
            setSizeManually: true,
 | 
			
		||||
            showLabel: false
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Disable all DnD methods
 | 
			
		||||
    _onDragBegin() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDragEnd() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handleDragOver() {
 | 
			
		||||
        return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    acceptDrop() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A container like StBin, but taking the child's scale into account
 | 
			
		||||
// when requesting a size
 | 
			
		||||
var DashItemContainer = GObject.registerClass(
 | 
			
		||||
@@ -475,19 +501,7 @@ var Dash = class Dash {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _createAppItem(app) {
 | 
			
		||||
        let appIcon = new AppDisplay.AppIcon(app,
 | 
			
		||||
                                             { setSizeManually: true,
 | 
			
		||||
                                               showLabel: false });
 | 
			
		||||
        if (appIcon._draggable) {
 | 
			
		||||
            appIcon._draggable.connect('drag-begin',
 | 
			
		||||
                                       () => {
 | 
			
		||||
                                           appIcon.actor.opacity = 50;
 | 
			
		||||
                                       });
 | 
			
		||||
            appIcon._draggable.connect('drag-end',
 | 
			
		||||
                                       () => {
 | 
			
		||||
                                           appIcon.actor.opacity = 255;
 | 
			
		||||
                                       });
 | 
			
		||||
        }
 | 
			
		||||
        let appIcon = new DashIcon(app);
 | 
			
		||||
 | 
			
		||||
        appIcon.connect('menu-state-changed',
 | 
			
		||||
                        (appIcon, opened) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,27 @@ var AnimationDirection = {
 | 
			
		||||
var APPICON_ANIMATION_OUT_SCALE = 3;
 | 
			
		||||
var APPICON_ANIMATION_OUT_TIME = 0.25;
 | 
			
		||||
 | 
			
		||||
const LEFT_DIVIDER_LEEWAY = 30;
 | 
			
		||||
const RIGHT_DIVIDER_LEEWAY = 30;
 | 
			
		||||
 | 
			
		||||
const NUDGE_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_ELASTIC;
 | 
			
		||||
const NUDGE_DURATION = 800;
 | 
			
		||||
 | 
			
		||||
const NUDGE_RETURN_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_QUINT;
 | 
			
		||||
const NUDGE_RETURN_DURATION = 300;
 | 
			
		||||
 | 
			
		||||
const NUDGE_FACTOR = 0.33;
 | 
			
		||||
 | 
			
		||||
const ICON_POSITION_DELAY = 25;
 | 
			
		||||
 | 
			
		||||
var DragLocation = {
 | 
			
		||||
    DEFAULT: 0,
 | 
			
		||||
    ON_ICON: 1,
 | 
			
		||||
    START_EDGE: 2,
 | 
			
		||||
    END_EDGE: 3,
 | 
			
		||||
    EMPTY_AREA: 4,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var BaseIcon = GObject.registerClass(
 | 
			
		||||
class BaseIcon extends St.Bin {
 | 
			
		||||
    _init(label, params) {
 | 
			
		||||
@@ -142,6 +163,10 @@ class BaseIcon extends St.Bin {
 | 
			
		||||
        // animating.
 | 
			
		||||
        zoomOutActor(this.child);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update() {
 | 
			
		||||
        this._createIconTexture(this.iconSize);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function clamp(value, min, max) {
 | 
			
		||||
@@ -342,6 +367,7 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
        let y = box.y1 + this.topPadding;
 | 
			
		||||
        let columnIndex = 0;
 | 
			
		||||
        let rowIndex = 0;
 | 
			
		||||
        let nChanged = 0;
 | 
			
		||||
        for (let i = 0; i < children.length; i++) {
 | 
			
		||||
            let childBox = this._calculateChildBox(children[i], x, y, box);
 | 
			
		||||
 | 
			
		||||
@@ -351,7 +377,16 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
            } else {
 | 
			
		||||
                if (!animating)
 | 
			
		||||
                    children[i].opacity = 255;
 | 
			
		||||
 | 
			
		||||
                // Figure out how much delay to apply
 | 
			
		||||
                if (!childBox.equal(children[i].get_allocation_box()))
 | 
			
		||||
                    nChanged++;
 | 
			
		||||
 | 
			
		||||
                children[i].save_easing_state();
 | 
			
		||||
                children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
 | 
			
		||||
                children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged);
 | 
			
		||||
                children[i].allocate(childBox, flags);
 | 
			
		||||
                children[i].restore_easing_state();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            columnIndex++;
 | 
			
		||||
@@ -691,6 +726,22 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
            this.add_actor(item.actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    moveItem(item, newPosition) {
 | 
			
		||||
        if (!this.contains(item.actor)) {
 | 
			
		||||
            log('Cannot move item not contained by the IconGrid');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let children = this.get_children();
 | 
			
		||||
        let visibleChildren = children.filter(c => c.is_visible());
 | 
			
		||||
        let visibleChildAtPosition = visibleChildren[newPosition];
 | 
			
		||||
        let realPosition = children.indexOf(visibleChildAtPosition);
 | 
			
		||||
 | 
			
		||||
        this.set_child_at_index(item.actor, realPosition);
 | 
			
		||||
 | 
			
		||||
        return realPosition;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeItem(item) {
 | 
			
		||||
        this.remove_child(item.actor);
 | 
			
		||||
    }
 | 
			
		||||
@@ -787,6 +838,223 @@ var IconGrid = GObject.registerClass({
 | 
			
		||||
        }
 | 
			
		||||
        return GLib.SOURCE_REMOVE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Drag n' Drop methods
 | 
			
		||||
 | 
			
		||||
    nudgeItemsAtIndex(index, dragLocation) {
 | 
			
		||||
        // No nudging when the cursor is in an empty area
 | 
			
		||||
        if (dragLocation == DragLocation.EMPTY_AREA || dragLocation == DragLocation.ON_ICON)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let children = this.get_children().filter(c => c.is_visible());
 | 
			
		||||
        let nudgeIndex = index;
 | 
			
		||||
        let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
 | 
			
		||||
 | 
			
		||||
        if (dragLocation != DragLocation.START_EDGE) {
 | 
			
		||||
            let leftItem = children[nudgeIndex - 1];
 | 
			
		||||
            let offset = rtl ? Math.floor(this._hItemSize * NUDGE_FACTOR) : Math.floor(-this._hItemSize * NUDGE_FACTOR);
 | 
			
		||||
            this._animateNudge(leftItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Nudge the icon to the right if we are the first item or not at the
 | 
			
		||||
        // end of row
 | 
			
		||||
        if (dragLocation != DragLocation.END_EDGE) {
 | 
			
		||||
            let rightItem = children[nudgeIndex];
 | 
			
		||||
            let offset = rtl ? Math.floor(-this._hItemSize * NUDGE_FACTOR) : Math.floor(this._hItemSize * NUDGE_FACTOR);
 | 
			
		||||
            this._animateNudge(rightItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeNudges() {
 | 
			
		||||
        let children = this.get_children().filter(c => c.is_visible());
 | 
			
		||||
        for (let index = 0; index < children.length; index++) {
 | 
			
		||||
            this._animateNudge(children[index],
 | 
			
		||||
                               NUDGE_RETURN_ANIMATION_TYPE,
 | 
			
		||||
                               NUDGE_RETURN_DURATION,
 | 
			
		||||
                               0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _animateNudge(item, animationType, duration, offset) {
 | 
			
		||||
        if (!item)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        item.save_easing_state();
 | 
			
		||||
        item.set_easing_mode(animationType);
 | 
			
		||||
        item.set_easing_duration(duration);
 | 
			
		||||
        item.translation_x = offset;
 | 
			
		||||
        item.restore_easing_state();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // This function is overriden by the PaginatedIconGrid subclass so we can
 | 
			
		||||
    // take into account the extra space when dragging from a folder
 | 
			
		||||
    _calculateDndRow(y) {
 | 
			
		||||
        let rowHeight = this._getVItemSize() + this._getSpacing();
 | 
			
		||||
        return Math.floor(y / rowHeight);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Returns the drop point index or -1 if we can't drop there
 | 
			
		||||
    canDropAt(x, y) {
 | 
			
		||||
        // This is an complex calculation, but in essence, we divide the grid
 | 
			
		||||
        // as:
 | 
			
		||||
        //
 | 
			
		||||
        //  left empty space
 | 
			
		||||
        //      |   left padding                          right padding
 | 
			
		||||
        //      |     |        width without padding               |
 | 
			
		||||
        // +--------+---+---------------------------------------+-----+
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |--------+-----------+----------+-------|     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |--------+-----------+----------+-------|     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |--------+-----------+----------+-------|     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // |        |   |        |           |          |       |     |
 | 
			
		||||
        // +--------+---+---------------------------------------+-----+
 | 
			
		||||
        //
 | 
			
		||||
        // The left empty space is immediately discarded, and ignored in all
 | 
			
		||||
        // calculations.
 | 
			
		||||
        //
 | 
			
		||||
        // The width (with paddings) is used to determine if we're dragging
 | 
			
		||||
        // over the left or right padding, and which column is being dragged
 | 
			
		||||
        // on.
 | 
			
		||||
        //
 | 
			
		||||
        // Finally, the width without padding is used to figure out where in
 | 
			
		||||
        // the icon (start edge, end edge, on it, etc) the cursor is.
 | 
			
		||||
 | 
			
		||||
        let [nColumns, usedWidth] = this._computeLayout(this.width);
 | 
			
		||||
 | 
			
		||||
        let leftEmptySpace;
 | 
			
		||||
        switch (this._xAlign) {
 | 
			
		||||
        case St.Align.START:
 | 
			
		||||
            leftEmptySpace = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case St.Align.MIDDLE:
 | 
			
		||||
            leftEmptySpace = Math.floor((this.width - usedWidth) / 2);
 | 
			
		||||
            break;
 | 
			
		||||
        case St.Align.END:
 | 
			
		||||
            leftEmptySpace = availWidth - usedWidth;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        x -= leftEmptySpace;
 | 
			
		||||
        y -= this.topPadding;
 | 
			
		||||
 | 
			
		||||
        let row = this._calculateDndRow(y);
 | 
			
		||||
 | 
			
		||||
        // Correct sx to handle the left padding to correctly calculate
 | 
			
		||||
        // the column
 | 
			
		||||
        let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
 | 
			
		||||
        let gridX = x - this.leftPadding;
 | 
			
		||||
 | 
			
		||||
        let widthWithoutPadding = usedWidth - this.leftPadding - this.rightPadding;
 | 
			
		||||
        let columnWidth = widthWithoutPadding / nColumns;
 | 
			
		||||
 | 
			
		||||
        let column;
 | 
			
		||||
        if (x < this.leftPadding)
 | 
			
		||||
            column = 0;
 | 
			
		||||
        else if (x > usedWidth - this.rightPadding)
 | 
			
		||||
            column = nColumns - 1;
 | 
			
		||||
        else
 | 
			
		||||
            column = Math.floor(gridX / columnWidth);
 | 
			
		||||
 | 
			
		||||
        let isFirstIcon = column == 0;
 | 
			
		||||
        let isLastIcon = column == nColumns - 1;
 | 
			
		||||
 | 
			
		||||
        // If we're outside of the grid, we are in an invalid drop location
 | 
			
		||||
        if (x < 0 || x > usedWidth)
 | 
			
		||||
            return [-1, DragLocation.DEFAULT];
 | 
			
		||||
 | 
			
		||||
        let children = this.get_children().filter(c => c.is_visible());
 | 
			
		||||
        let childIndex = Math.min((row * nColumns) + column, children.length);
 | 
			
		||||
 | 
			
		||||
        // If we're above the grid vertically, we are in an invalid
 | 
			
		||||
        // drop location
 | 
			
		||||
        if (childIndex < 0)
 | 
			
		||||
            return [-1, DragLocation.DEFAULT];
 | 
			
		||||
 | 
			
		||||
        // If we're past the last visible element in the grid,
 | 
			
		||||
        // we might be allowed to drop there.
 | 
			
		||||
        if (childIndex >= children.length)
 | 
			
		||||
            return [children.length, DragLocation.EMPTY_AREA];
 | 
			
		||||
 | 
			
		||||
        let child = children[childIndex];
 | 
			
		||||
        let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] = child.get_preferred_size();
 | 
			
		||||
 | 
			
		||||
        // This is the width of the cell that contains the icon
 | 
			
		||||
        // (excluding spacing between cells)
 | 
			
		||||
        let childIconWidth = Math.max(this._getHItemSize(), childNaturalWidth);
 | 
			
		||||
 | 
			
		||||
        // Calculate the original position of the child icon (prior to nudging)
 | 
			
		||||
        let childX;
 | 
			
		||||
        if (rtl)
 | 
			
		||||
            childX = widthWithoutPadding - (column * columnWidth) - childIconWidth;
 | 
			
		||||
        else
 | 
			
		||||
            childX = column * columnWidth;
 | 
			
		||||
 | 
			
		||||
        let iconLeftX = childX + LEFT_DIVIDER_LEEWAY;
 | 
			
		||||
        let iconRightX = childX + childIconWidth - RIGHT_DIVIDER_LEEWAY
 | 
			
		||||
 | 
			
		||||
        let dropIndex;
 | 
			
		||||
        let dragLocation;
 | 
			
		||||
 | 
			
		||||
        x -= this.leftPadding;
 | 
			
		||||
 | 
			
		||||
        if (x < iconLeftX) {
 | 
			
		||||
            // We are to the left of the icon target
 | 
			
		||||
            if (isFirstIcon || x < 0) {
 | 
			
		||||
                // We are before the leftmost icon on the grid
 | 
			
		||||
                if (rtl) {
 | 
			
		||||
                    dropIndex = childIndex + 1;
 | 
			
		||||
                    dragLocation = DragLocation.END_EDGE;
 | 
			
		||||
                } else {
 | 
			
		||||
                    dropIndex = childIndex;
 | 
			
		||||
                    dragLocation = DragLocation.START_EDGE;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // We are between the previous icon (next in RTL) and this one
 | 
			
		||||
                if (rtl)
 | 
			
		||||
                    dropIndex = childIndex + 1;
 | 
			
		||||
                else
 | 
			
		||||
                    dropIndex = childIndex;
 | 
			
		||||
 | 
			
		||||
                dragLocation = DragLocation.DEFAULT;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (x >= iconRightX) {
 | 
			
		||||
            // We are to the right of the icon target
 | 
			
		||||
            if (childIndex >= children.length) {
 | 
			
		||||
                // We are beyond the last valid icon
 | 
			
		||||
                // (to the right of the app store / trash can, if present)
 | 
			
		||||
                dropIndex = -1;
 | 
			
		||||
                dragLocation = DragLocation.DEFAULT;
 | 
			
		||||
            } else if (isLastIcon || x >= widthWithoutPadding) {
 | 
			
		||||
                // We are beyond the rightmost icon on the grid
 | 
			
		||||
                if (rtl) {
 | 
			
		||||
                    dropIndex = childIndex;
 | 
			
		||||
                    dragLocation = DragLocation.START_EDGE;
 | 
			
		||||
                } else {
 | 
			
		||||
                    dropIndex = childIndex + 1;
 | 
			
		||||
                    dragLocation = DragLocation.END_EDGE;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // We are between this icon and the next one (previous in RTL)
 | 
			
		||||
                if (rtl)
 | 
			
		||||
                    dropIndex = childIndex;
 | 
			
		||||
                else
 | 
			
		||||
                    dropIndex = childIndex + 1;
 | 
			
		||||
 | 
			
		||||
                dragLocation = DragLocation.DEFAULT;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // We are over the icon target area
 | 
			
		||||
            dropIndex = childIndex;
 | 
			
		||||
            dragLocation = DragLocation.ON_ICON;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [dropIndex, dragLocation];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
@@ -839,10 +1107,21 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
        let x = box.x1 + leftEmptySpace + this.leftPadding;
 | 
			
		||||
        let y = box.y1 + this.topPadding;
 | 
			
		||||
        let columnIndex = 0;
 | 
			
		||||
        let nChanged = 0;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < children.length; i++) {
 | 
			
		||||
            let childBox = this._calculateChildBox(children[i], x, y, box);
 | 
			
		||||
 | 
			
		||||
            // Figure out how much delay to apply
 | 
			
		||||
            if (!childBox.equal(children[i].get_allocation_box()))
 | 
			
		||||
                nChanged++;
 | 
			
		||||
 | 
			
		||||
            children[i].save_easing_state();
 | 
			
		||||
            children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
 | 
			
		||||
            children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged);
 | 
			
		||||
            children[i].allocate(childBox, flags);
 | 
			
		||||
            children[i].restore_easing_state();
 | 
			
		||||
 | 
			
		||||
            children[i].show();
 | 
			
		||||
 | 
			
		||||
            columnIndex++;
 | 
			
		||||
@@ -861,6 +1140,23 @@ var PaginatedIconGrid = GObject.registerClass({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Overridden from IconGrid
 | 
			
		||||
    _calculateDndRow(y) {
 | 
			
		||||
        let row = super._calculateDndRow(y);
 | 
			
		||||
 | 
			
		||||
        // If there's no extra space, just return the current value and maintain
 | 
			
		||||
        // the same behavior when without a folder opened.
 | 
			
		||||
        if (!this._extraSpaceData)
 | 
			
		||||
            return row;
 | 
			
		||||
 | 
			
		||||
        let [ baseRow, nRowsUp, nRowsDown ] = this._extraSpaceData;
 | 
			
		||||
        let newRow = row + nRowsUp;
 | 
			
		||||
 | 
			
		||||
        if (row > baseRow)
 | 
			
		||||
            newRow -= nRowsDown;
 | 
			
		||||
 | 
			
		||||
        return newRow;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getChildrenToAnimate() {
 | 
			
		||||
        let children = this._getVisibleChildren();
 | 
			
		||||
        let firstIndex = this._childrenPerPage * this.currentPage;
 | 
			
		||||
 
 | 
			
		||||
@@ -424,17 +424,6 @@ var ControlsManager = class {
 | 
			
		||||
        layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', this._updateSpacerVisibility.bind(this));
 | 
			
		||||
        Main.overview.connect('item-drag-begin', () => {
 | 
			
		||||
            let activePage = this.viewSelector.getActivePage();
 | 
			
		||||
            if (activePage != ViewSelector.ViewPage.WINDOWS)
 | 
			
		||||
                this.viewSelector.fadeHalf();
 | 
			
		||||
        });
 | 
			
		||||
        Main.overview.connect('item-drag-end', () => {
 | 
			
		||||
            this.viewSelector.fadeIn();
 | 
			
		||||
        });
 | 
			
		||||
        Main.overview.connect('item-drag-cancelled', () => {
 | 
			
		||||
            this.viewSelector.fadeIn();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _updateWorkspacesGeometry() {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,14 @@
 | 
			
		||||
#include "shell-app-system-private.h"
 | 
			
		||||
#include "shell-global.h"
 | 
			
		||||
#include "shell-util.h"
 | 
			
		||||
#include "st.h"
 | 
			
		||||
 | 
			
		||||
/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That
 | 
			
		||||
 * should be plenty of time for even a slow spinning drive to update
 | 
			
		||||
 * the icon cache.
 | 
			
		||||
 */
 | 
			
		||||
#define RESCAN_TIMEOUT_MS 2500
 | 
			
		||||
#define MAX_RESCAN_RETRIES 6
 | 
			
		||||
 | 
			
		||||
/* Vendor prefixes are something that can be preprended to a .desktop
 | 
			
		||||
 * file name.  Undo this.
 | 
			
		||||
@@ -51,6 +59,9 @@ struct _ShellAppSystemPrivate {
 | 
			
		||||
  GHashTable *id_to_app;
 | 
			
		||||
  GHashTable *startup_wm_class_to_id;
 | 
			
		||||
  GList *installed_apps;
 | 
			
		||||
 | 
			
		||||
  guint rescan_icons_timeout_id;
 | 
			
		||||
  guint n_rescan_retries;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void shell_app_system_finalize (GObject *object);
 | 
			
		||||
@@ -157,12 +168,54 @@ stale_app_remove_func (gpointer key,
 | 
			
		||||
  return app_is_stale (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
rescan_icon_theme_cb (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv;
 | 
			
		||||
  ShellAppSystem *self;
 | 
			
		||||
  StTextureCache *texture_cache;
 | 
			
		||||
  gboolean rescanned;
 | 
			
		||||
 | 
			
		||||
  self = (ShellAppSystem *) user_data;
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  texture_cache = st_texture_cache_get_default ();
 | 
			
		||||
  rescanned = st_texture_cache_rescan_icon_theme (texture_cache);
 | 
			
		||||
 | 
			
		||||
  priv->n_rescan_retries++;
 | 
			
		||||
 | 
			
		||||
  if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES)
 | 
			
		||||
    {
 | 
			
		||||
      priv->n_rescan_retries = 0;
 | 
			
		||||
      priv->rescan_icons_timeout_id = 0;
 | 
			
		||||
      return G_SOURCE_REMOVE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return G_SOURCE_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
rescan_icon_theme (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystemPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->n_rescan_retries = 0;
 | 
			
		||||
 | 
			
		||||
  if (priv->rescan_icons_timeout_id > 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS,
 | 
			
		||||
                                                 rescan_icon_theme_cb,
 | 
			
		||||
                                                 self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
installed_changed (GAppInfoMonitor *monitor,
 | 
			
		||||
                   gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  ShellAppSystem *self = user_data;
 | 
			
		||||
 | 
			
		||||
  rescan_icon_theme (self);
 | 
			
		||||
  scan_startup_wm_class_to_id (self);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
 | 
			
		||||
@@ -200,6 +253,7 @@ shell_app_system_finalize (GObject *object)
 | 
			
		||||
  g_hash_table_destroy (priv->id_to_app);
 | 
			
		||||
  g_hash_table_destroy (priv->startup_wm_class_to_id);
 | 
			
		||||
  g_list_free_full (priv->installed_apps, g_object_unref);
 | 
			
		||||
  g_clear_handle_id (&priv->rescan_icons_timeout_id, g_source_remove);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -150,6 +150,14 @@ on_icon_theme_changed (StSettings     *settings,
 | 
			
		||||
  g_signal_emit (cache, signals[ICON_THEME_CHANGED], 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_gtk_icon_theme_changed (GtkIconTheme   *icon_theme,
 | 
			
		||||
                           StTextureCache *self)
 | 
			
		||||
{
 | 
			
		||||
  st_texture_cache_evict_icons (self);
 | 
			
		||||
  g_signal_emit (self, signals[ICON_THEME_CHANGED], 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_texture_cache_init (StTextureCache *self)
 | 
			
		||||
{
 | 
			
		||||
@@ -160,6 +168,8 @@ st_texture_cache_init (StTextureCache *self)
 | 
			
		||||
  self->priv->icon_theme = gtk_icon_theme_new ();
 | 
			
		||||
  gtk_icon_theme_add_resource_path (self->priv->icon_theme,
 | 
			
		||||
                                    "/org/gnome/shell/theme/icons");
 | 
			
		||||
  g_signal_connect (self->priv->icon_theme, "changed",
 | 
			
		||||
                    G_CALLBACK (on_gtk_icon_theme_changed), self);
 | 
			
		||||
 | 
			
		||||
  settings = st_settings_get ();
 | 
			
		||||
  g_signal_connect (settings, "notify::gtk-icon-theme",
 | 
			
		||||
@@ -1557,3 +1567,11 @@ st_texture_cache_get_default (void)
 | 
			
		||||
    instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL);
 | 
			
		||||
  return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
st_texture_cache_rescan_icon_theme (StTextureCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  StTextureCachePrivate *priv = cache->priv;
 | 
			
		||||
 | 
			
		||||
  return gtk_icon_theme_rescan_if_needed (priv->icon_theme);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -113,4 +113,6 @@ CoglTexture * st_texture_cache_load (StTextureCache       *cache,
 | 
			
		||||
                                     void                 *data,
 | 
			
		||||
                                     GError              **error);
 | 
			
		||||
 | 
			
		||||
gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache);
 | 
			
		||||
 | 
			
		||||
#endif /* __ST_TEXTURE_CACHE_H__ */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user