Bug 589316 - Add application/window icon to overlay windows
To better distinguish between vast fields of white of which many windows are composed, add the application icon to the bottom right of the window. We fade them in to avoid an abrupt feel. The icons are in the workspaces group, not individual workspace groups to avoid having to adjust them when we scale the workspaces. Replace Workspace._lookupIndexAndClone with Workspace.lookupIndex, and make the caller go from index to clone, or clone and index.
This commit is contained in:
parent
c23b9ee192
commit
4d52c10958
@ -121,9 +121,10 @@ WindowClone.prototype = {
|
|||||||
_onDragBegin : function (draggable, time) {
|
_onDragBegin : function (draggable, time) {
|
||||||
this._inDrag = true;
|
this._inDrag = true;
|
||||||
this._updateTitle();
|
this._updateTitle();
|
||||||
|
this.emit('drag-begin');
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDragEnd : function (draggable, time) {
|
_onDragEnd : function (draggable, time, snapback) {
|
||||||
this._inDrag = false;
|
this._inDrag = false;
|
||||||
|
|
||||||
// Most likely, the clone is going to move away from the
|
// Most likely, the clone is going to move away from the
|
||||||
@ -133,6 +134,8 @@ WindowClone.prototype = {
|
|||||||
// better to have the label mysteriously missing than
|
// better to have the label mysteriously missing than
|
||||||
// mysteriously present
|
// mysteriously present
|
||||||
this._havePointer = false;
|
this._havePointer = false;
|
||||||
|
|
||||||
|
this.emit('drag-end');
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called by Tweener
|
// Called by Tweener
|
||||||
@ -155,16 +158,7 @@ WindowClone.prototype = {
|
|||||||
padding: 4,
|
padding: 4,
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
orientation: Big.BoxOrientation.HORIZONTAL });
|
orientation: Big.BoxOrientation.HORIZONTAL });
|
||||||
|
|
||||||
let icon = this.metaWindow.mini_icon;
|
|
||||||
let iconTexture = new Clutter.Texture({ x: this.actor.x,
|
|
||||||
y: this.actor.y + this.actor.height - 16,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
keep_aspect_ratio: true });
|
|
||||||
Shell.clutter_texture_set_from_pixbuf(iconTexture, icon);
|
|
||||||
box.append(iconTexture, Big.BoxPackFlags.NONE);
|
|
||||||
|
|
||||||
let title = new Clutter.Text({ color: WINDOWCLONE_TITLE_COLOR,
|
let title = new Clutter.Text({ color: WINDOWCLONE_TITLE_COLOR,
|
||||||
font_name: "Sans 12",
|
font_name: "Sans 12",
|
||||||
text: this.metaWindow.title,
|
text: this.metaWindow.title,
|
||||||
@ -258,18 +252,26 @@ DesktopClone.prototype = {
|
|||||||
Signals.addSignalMethods(DesktopClone.prototype);
|
Signals.addSignalMethods(DesktopClone.prototype);
|
||||||
|
|
||||||
|
|
||||||
function Workspace(workspaceNum) {
|
/**
|
||||||
this._init(workspaceNum);
|
* @workspaceNum: Workspace index
|
||||||
|
* @parentActor: The actor which will be the parent of this workspace;
|
||||||
|
* we need this in order to add chrome such as the icons
|
||||||
|
* on top of the windows without having them be scaled.
|
||||||
|
*/
|
||||||
|
function Workspace(workspaceNum, parentActor) {
|
||||||
|
this._init(workspaceNum, parentActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Workspace.prototype = {
|
Workspace.prototype = {
|
||||||
_init : function(workspaceNum) {
|
_init : function(workspaceNum, parentActor) {
|
||||||
let me = this;
|
let me = this;
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
|
|
||||||
this.workspaceNum = workspaceNum;
|
this.workspaceNum = workspaceNum;
|
||||||
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
||||||
|
|
||||||
|
this.parentActor = parentActor;
|
||||||
|
|
||||||
this.actor = new Clutter.Group();
|
this.actor = new Clutter.Group();
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
this.scale = 1.0;
|
this.scale = 1.0;
|
||||||
@ -298,6 +300,7 @@ Workspace.prototype = {
|
|||||||
// Create clones for remaining windows that should be
|
// Create clones for remaining windows that should be
|
||||||
// visible in the overlay
|
// visible in the overlay
|
||||||
this._windows = [this._desktop];
|
this._windows = [this._desktop];
|
||||||
|
this._windowIcons = [ null ];
|
||||||
for (let i = 0; i < windows.length; i++) {
|
for (let i = 0; i < windows.length; i++) {
|
||||||
if (this._isOverlayWindow(windows[i])) {
|
if (this._isOverlayWindow(windows[i])) {
|
||||||
this._addWindowClone(windows[i]);
|
this._addWindowClone(windows[i]);
|
||||||
@ -364,21 +367,19 @@ Workspace.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_lookupIndexAndClone: function (metaWindow) {
|
_lookupIndex: function (metaWindow) {
|
||||||
let index, clone;
|
let index, clone;
|
||||||
for (let i = 0; i < this._windows.length; i++) {
|
for (let i = 0; i < this._windows.length; i++) {
|
||||||
if (this._windows[i].metaWindow == metaWindow) {
|
if (this._windows[i].metaWindow == metaWindow) {
|
||||||
index = i;
|
return i;
|
||||||
clone = this._windows[index];
|
|
||||||
return [index, clone];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [-1, null];
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
lookupCloneForMetaWindow: function (metaWindow) {
|
lookupCloneForMetaWindow: function (metaWindow) {
|
||||||
let [index, clone] = this._lookupIndexAndClone (metaWindow);
|
let index = this._lookupIndex (metaWindow);
|
||||||
return clone;
|
return index < 0 ? null : this._windows[index];
|
||||||
},
|
},
|
||||||
|
|
||||||
_adjustRemoveButton : function() {
|
_adjustRemoveButton : function() {
|
||||||
@ -440,6 +441,7 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
for (let i = 1; i < this._windows.length; i++) {
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
let clone = this._windows[i];
|
let clone = this._windows[i];
|
||||||
|
let icon = this._windowIcons[i];
|
||||||
clone.stackAbove = this._windows[i - 1].actor;
|
clone.stackAbove = this._windows[i - 1].actor;
|
||||||
|
|
||||||
let [xCenter, yCenter, fraction] = this._computeWindowPosition(i);
|
let [xCenter, yCenter, fraction] = this._computeWindowPosition(i);
|
||||||
@ -450,6 +452,7 @@ Workspace.prototype = {
|
|||||||
let desiredSize = global.screen_width * fraction;
|
let desiredSize = global.screen_width * fraction;
|
||||||
let scale = Math.min(desiredSize / size, 1.0 / this.scale);
|
let scale = Math.min(desiredSize / size, 1.0 / this.scale);
|
||||||
|
|
||||||
|
icon.hide();
|
||||||
Tweener.addTween(clone.actor,
|
Tweener.addTween(clone.actor,
|
||||||
{ x: xCenter - 0.5 * scale * clone.actor.width,
|
{ x: xCenter - 0.5 * scale * clone.actor.width,
|
||||||
y: yCenter - 0.5 * scale * clone.actor.height,
|
y: yCenter - 0.5 * scale * clone.actor.height,
|
||||||
@ -457,22 +460,63 @@ Workspace.prototype = {
|
|||||||
scale_y: scale,
|
scale_y: scale,
|
||||||
workspace_relative: workspaceZooming ? this : null,
|
workspace_relative: workspaceZooming ? this : null,
|
||||||
time: Overlay.ANIMATION_TIME,
|
time: Overlay.ANIMATION_TIME,
|
||||||
transition: "easeOutQuad"
|
transition: "easeOutQuad",
|
||||||
|
onComplete: Lang.bind(this, function() {
|
||||||
|
this._fadeInWindowIcon(clone, icon);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_fadeInWindowIcon: function (clone, icon) {
|
||||||
|
icon.opacity = 0;
|
||||||
|
icon.show();
|
||||||
|
let [parentX, parentY] = icon.get_parent().get_transformed_position();
|
||||||
|
let [cloneX, cloneY] = clone.actor.get_transformed_position();
|
||||||
|
let [cloneWidth, cloneHeight] = clone.actor.get_transformed_size();
|
||||||
|
// Note we only round the first part, because we're still going to be
|
||||||
|
// positioned relative to the parent. By subtracting a possibly
|
||||||
|
// non-integral parent X/Y we cancel it out.
|
||||||
|
let x = Math.round(cloneX + cloneWidth - icon.width) - parentX;
|
||||||
|
let y = Math.round(cloneY + cloneHeight - icon.height) - parentY;
|
||||||
|
icon.set_position(x, y);
|
||||||
|
icon.raise(this.actor);
|
||||||
|
Tweener.addTween(icon,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: Overlay.ANIMATION_TIME,
|
||||||
|
transition: "easeOutQuad" });
|
||||||
|
},
|
||||||
|
|
||||||
|
_fadeInAllIcons: function () {
|
||||||
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
|
let clone = this._windows[i];
|
||||||
|
let icon = this._windowIcons[i];
|
||||||
|
this._fadeInWindowIcon(clone, icon);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_hideAllIcons: function () {
|
||||||
|
for (let i = 1; i < this._windows.length; i++) {
|
||||||
|
let icon = this._windowIcons[i];
|
||||||
|
icon.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
let win = metaWin.get_compositor_private();
|
let win = metaWin.get_compositor_private();
|
||||||
|
|
||||||
// find the position of the window in our list
|
// find the position of the window in our list
|
||||||
let [index, clone] = this._lookupIndexAndClone (metaWin);
|
let index = this._lookupIndex (metaWin);
|
||||||
|
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
let clone = this._windows[index];
|
||||||
|
let icon = this._windowIcons[index];
|
||||||
|
|
||||||
this._windows.splice(index, 1);
|
this._windows.splice(index, 1);
|
||||||
|
this._windowIcons.splice(index, 1);
|
||||||
|
|
||||||
// If metaWin.get_compositor_private() returned non-NULL, that
|
// If metaWin.get_compositor_private() returned non-NULL, that
|
||||||
// means the window still exists (and is just being moved to
|
// means the window still exists (and is just being moved to
|
||||||
@ -490,6 +534,7 @@ Workspace.prototype = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
clone.destroy();
|
clone.destroy();
|
||||||
|
icon.destroy();
|
||||||
|
|
||||||
this._positionWindows(false);
|
this._positionWindows(false);
|
||||||
this.updateRemovable();
|
this.updateRemovable();
|
||||||
@ -559,8 +604,10 @@ Workspace.prototype = {
|
|||||||
|
|
||||||
// Animates the return from overlay mode
|
// Animates the return from overlay mode
|
||||||
zoomFromOverlay : function() {
|
zoomFromOverlay : function() {
|
||||||
this.leavingOverlay = true;
|
this.leavingOverlay = true;
|
||||||
|
|
||||||
|
this._hideAllIcons();
|
||||||
|
|
||||||
Tweener.addTween(this.actor,
|
Tweener.addTween(this.actor,
|
||||||
{ x: this.fullSizeX,
|
{ x: this.fullSizeX,
|
||||||
y: this.fullSizeY,
|
y: this.fullSizeY,
|
||||||
@ -592,16 +639,18 @@ Workspace.prototype = {
|
|||||||
// Animates grid shrinking/expanding when a row or column
|
// Animates grid shrinking/expanding when a row or column
|
||||||
// of workspaces is added or removed
|
// of workspaces is added or removed
|
||||||
resizeToGrid : function (oldScale) {
|
resizeToGrid : function (oldScale) {
|
||||||
|
this._hideAllIcons();
|
||||||
Tweener.addTween(this.actor,
|
Tweener.addTween(this.actor,
|
||||||
{ x: this.gridX,
|
{ x: this.gridX,
|
||||||
y: this.gridY,
|
y: this.gridY,
|
||||||
scale_x: this.scale,
|
scale_x: this.scale,
|
||||||
scale_y: this.scale,
|
scale_y: this.scale,
|
||||||
time: Overlay.ANIMATION_TIME,
|
time: Overlay.ANIMATION_TIME,
|
||||||
transition: "easeOutQuad"
|
transition: "easeOutQuad",
|
||||||
|
onComplete: Lang.bind(this, this._fadeInAllIcons)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Animates the addition of a new (empty) workspace
|
// Animates the addition of a new (empty) workspace
|
||||||
slideIn : function(oldScale) {
|
slideIn : function(oldScale) {
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
@ -630,6 +679,8 @@ Workspace.prototype = {
|
|||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
let destX = this.actor.x, destY = this.actor.y;
|
let destX = this.actor.x, destY = this.actor.y;
|
||||||
|
|
||||||
|
this._hideAllIcons();
|
||||||
|
|
||||||
if (this.gridCol > this.gridRow)
|
if (this.gridCol > this.gridRow)
|
||||||
destX = global.screen_width;
|
destX = global.screen_width;
|
||||||
else
|
else
|
||||||
@ -682,16 +733,47 @@ Workspace.prototype = {
|
|||||||
return !win.is_override_redirect();
|
return !win.is_override_redirect();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_createWindowIcon: function(window) {
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
let appMon = Shell.AppMonitor.get_default()
|
||||||
|
let appInfo = appMon.get_window_app(window.metaWindow);
|
||||||
|
let iconTexture = null;
|
||||||
|
// The design is application based, so prefer the application
|
||||||
|
// icon here if we have it. FIXME - should move this fallback code
|
||||||
|
// into ShellAppMonitor.
|
||||||
|
if (appInfo) {
|
||||||
|
iconTexture = appInfo.create_icon_texture(48);
|
||||||
|
} else {
|
||||||
|
let icon = window.metaWindow.icon;
|
||||||
|
iconTexture = new Clutter.Texture({ width: 48,
|
||||||
|
height: 48,
|
||||||
|
keep_aspect_ratio: true });
|
||||||
|
Shell.clutter_texture_set_from_pixbuf(iconTexture, icon);
|
||||||
|
}
|
||||||
|
return iconTexture;
|
||||||
|
},
|
||||||
|
|
||||||
// Create a clone of a (non-desktop) window and add it to the window list
|
// Create a clone of a (non-desktop) window and add it to the window list
|
||||||
_addWindowClone : function(win) {
|
_addWindowClone : function(win) {
|
||||||
|
let icon = this._createWindowIcon(win);
|
||||||
|
this.parentActor.add_actor(icon);
|
||||||
|
|
||||||
let clone = new WindowClone(win);
|
let clone = new WindowClone(win);
|
||||||
clone.connect('selected',
|
clone.connect('selected',
|
||||||
Lang.bind(this, this._onCloneSelected));
|
Lang.bind(this, this._onCloneSelected));
|
||||||
clone.connect('dragged',
|
clone.connect('drag-begin',
|
||||||
Lang.bind(this, this._onCloneDragged));
|
Lang.bind(this, function() {
|
||||||
|
icon.hide();
|
||||||
|
}));
|
||||||
|
clone.connect('drag-end',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
icon.show();
|
||||||
|
}));
|
||||||
|
|
||||||
this.actor.add_actor(clone.actor);
|
this.actor.add_actor(clone.actor);
|
||||||
|
|
||||||
this._windows.push(clone);
|
this._windows.push(clone);
|
||||||
|
this._windowIcons.push(icon);
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
},
|
},
|
||||||
@ -717,10 +799,6 @@ Workspace.prototype = {
|
|||||||
return [xCenter, yCenter, fraction];
|
return [xCenter, yCenter, fraction];
|
||||||
},
|
},
|
||||||
|
|
||||||
_onCloneDragged : function (clone, stageX, stageY, time) {
|
|
||||||
this.emit('window-dragged', clone, stageX, stageY, time);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCloneSelected : function (clone, time) {
|
_onCloneSelected : function (clone, time) {
|
||||||
Main.overlay.activateWindow(clone.metaWindow, time);
|
Main.overlay.activateWindow(clone.metaWindow, time);
|
||||||
},
|
},
|
||||||
@ -1052,7 +1130,7 @@ Workspaces.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_addWorkspaceActor : function(workspaceNum) {
|
_addWorkspaceActor : function(workspaceNum) {
|
||||||
let workspace = new Workspace(workspaceNum);
|
let workspace = new Workspace(workspaceNum, this.actor);
|
||||||
this._workspaces[workspaceNum] = workspace;
|
this._workspaces[workspaceNum] = workspace;
|
||||||
this.actor.add_actor(workspace.actor);
|
this.actor.add_actor(workspace.actor);
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user