Compare commits
36 Commits
citadel
...
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.
|
the shell.
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</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"/>
|
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
|
@ -1514,6 +1514,9 @@ StScrollBar {
|
|||||||
border-image: none;
|
border-image: none;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
&:drop .overview-icon {
|
||||||
|
background-color: transparentize($selected_bg_color,.15);
|
||||||
|
}
|
||||||
&:active .overview-icon,
|
&:active .overview-icon,
|
||||||
&:checked .overview-icon {
|
&:checked .overview-icon {
|
||||||
background-color: transparentize(darken($osd_bg_color,10%), 0.5);
|
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
|
// A container like StBin, but taking the child's scale into account
|
||||||
// when requesting a size
|
// when requesting a size
|
||||||
var DashItemContainer = GObject.registerClass(
|
var DashItemContainer = GObject.registerClass(
|
||||||
@ -475,19 +501,7 @@ var Dash = class Dash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createAppItem(app) {
|
_createAppItem(app) {
|
||||||
let appIcon = new AppDisplay.AppIcon(app,
|
let appIcon = new DashIcon(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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
appIcon.connect('menu-state-changed',
|
appIcon.connect('menu-state-changed',
|
||||||
(appIcon, opened) => {
|
(appIcon, opened) => {
|
||||||
|
@ -29,6 +29,27 @@ var AnimationDirection = {
|
|||||||
var APPICON_ANIMATION_OUT_SCALE = 3;
|
var APPICON_ANIMATION_OUT_SCALE = 3;
|
||||||
var APPICON_ANIMATION_OUT_TIME = 0.25;
|
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(
|
var BaseIcon = GObject.registerClass(
|
||||||
class BaseIcon extends St.Bin {
|
class BaseIcon extends St.Bin {
|
||||||
_init(label, params) {
|
_init(label, params) {
|
||||||
@ -142,6 +163,10 @@ class BaseIcon extends St.Bin {
|
|||||||
// animating.
|
// animating.
|
||||||
zoomOutActor(this.child);
|
zoomOutActor(this.child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this._createIconTexture(this.iconSize);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function clamp(value, min, max) {
|
function clamp(value, min, max) {
|
||||||
@ -342,6 +367,7 @@ var IconGrid = GObject.registerClass({
|
|||||||
let y = box.y1 + this.topPadding;
|
let y = box.y1 + this.topPadding;
|
||||||
let columnIndex = 0;
|
let columnIndex = 0;
|
||||||
let rowIndex = 0;
|
let rowIndex = 0;
|
||||||
|
let nChanged = 0;
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
let childBox = this._calculateChildBox(children[i], x, y, box);
|
let childBox = this._calculateChildBox(children[i], x, y, box);
|
||||||
|
|
||||||
@ -351,7 +377,16 @@ var IconGrid = GObject.registerClass({
|
|||||||
} else {
|
} else {
|
||||||
if (!animating)
|
if (!animating)
|
||||||
children[i].opacity = 255;
|
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].allocate(childBox, flags);
|
||||||
|
children[i].restore_easing_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
columnIndex++;
|
columnIndex++;
|
||||||
@ -691,6 +726,22 @@ var IconGrid = GObject.registerClass({
|
|||||||
this.add_actor(item.actor);
|
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) {
|
removeItem(item) {
|
||||||
this.remove_child(item.actor);
|
this.remove_child(item.actor);
|
||||||
}
|
}
|
||||||
@ -787,6 +838,223 @@ var IconGrid = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
return GLib.SOURCE_REMOVE;
|
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({
|
var PaginatedIconGrid = GObject.registerClass({
|
||||||
@ -839,10 +1107,21 @@ var PaginatedIconGrid = GObject.registerClass({
|
|||||||
let x = box.x1 + leftEmptySpace + this.leftPadding;
|
let x = box.x1 + leftEmptySpace + this.leftPadding;
|
||||||
let y = box.y1 + this.topPadding;
|
let y = box.y1 + this.topPadding;
|
||||||
let columnIndex = 0;
|
let columnIndex = 0;
|
||||||
|
let nChanged = 0;
|
||||||
|
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
let childBox = this._calculateChildBox(children[i], x, y, box);
|
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].allocate(childBox, flags);
|
||||||
|
children[i].restore_easing_state();
|
||||||
|
|
||||||
children[i].show();
|
children[i].show();
|
||||||
|
|
||||||
columnIndex++;
|
columnIndex++;
|
||||||
@ -861,6 +1140,23 @@ var PaginatedIconGrid = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Overridden from IconGrid
|
// 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() {
|
_getChildrenToAnimate() {
|
||||||
let children = this._getVisibleChildren();
|
let children = this._getVisibleChildren();
|
||||||
let firstIndex = this._childrenPerPage * this.currentPage;
|
let firstIndex = this._childrenPerPage * this.currentPage;
|
||||||
|
@ -424,17 +424,6 @@ var ControlsManager = class {
|
|||||||
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
|
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
|
||||||
|
|
||||||
Main.overview.connect('showing', this._updateSpacerVisibility.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() {
|
_updateWorkspacesGeometry() {
|
||||||
|
@ -14,6 +14,14 @@
|
|||||||
#include "shell-app-system-private.h"
|
#include "shell-app-system-private.h"
|
||||||
#include "shell-global.h"
|
#include "shell-global.h"
|
||||||
#include "shell-util.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
|
/* Vendor prefixes are something that can be preprended to a .desktop
|
||||||
* file name. Undo this.
|
* file name. Undo this.
|
||||||
@ -51,6 +59,9 @@ struct _ShellAppSystemPrivate {
|
|||||||
GHashTable *id_to_app;
|
GHashTable *id_to_app;
|
||||||
GHashTable *startup_wm_class_to_id;
|
GHashTable *startup_wm_class_to_id;
|
||||||
GList *installed_apps;
|
GList *installed_apps;
|
||||||
|
|
||||||
|
guint rescan_icons_timeout_id;
|
||||||
|
guint n_rescan_retries;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_app_system_finalize (GObject *object);
|
static void shell_app_system_finalize (GObject *object);
|
||||||
@ -157,12 +168,54 @@ stale_app_remove_func (gpointer key,
|
|||||||
return app_is_stale (value);
|
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
|
static void
|
||||||
installed_changed (GAppInfoMonitor *monitor,
|
installed_changed (GAppInfoMonitor *monitor,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
ShellAppSystem *self = user_data;
|
ShellAppSystem *self = user_data;
|
||||||
|
|
||||||
|
rescan_icon_theme (self);
|
||||||
scan_startup_wm_class_to_id (self);
|
scan_startup_wm_class_to_id (self);
|
||||||
|
|
||||||
g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
|
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->id_to_app);
|
||||||
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
g_hash_table_destroy (priv->startup_wm_class_to_id);
|
||||||
g_list_free_full (priv->installed_apps, g_object_unref);
|
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);
|
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);
|
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
|
static void
|
||||||
st_texture_cache_init (StTextureCache *self)
|
st_texture_cache_init (StTextureCache *self)
|
||||||
{
|
{
|
||||||
@ -160,6 +168,8 @@ st_texture_cache_init (StTextureCache *self)
|
|||||||
self->priv->icon_theme = gtk_icon_theme_new ();
|
self->priv->icon_theme = gtk_icon_theme_new ();
|
||||||
gtk_icon_theme_add_resource_path (self->priv->icon_theme,
|
gtk_icon_theme_add_resource_path (self->priv->icon_theme,
|
||||||
"/org/gnome/shell/theme/icons");
|
"/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 ();
|
settings = st_settings_get ();
|
||||||
g_signal_connect (settings, "notify::gtk-icon-theme",
|
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);
|
instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL);
|
||||||
return instance;
|
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,
|
void *data,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache);
|
||||||
|
|
||||||
#endif /* __ST_TEXTURE_CACHE_H__ */
|
#endif /* __ST_TEXTURE_CACHE_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user