c93767768c
The code that loads SHELL_BACKGROUND_IMAGE, which is used to load the performance background was loading it in WALLPAPER mode, not ZOOM mode. Zoom mode is what we use for the actual GNOME defaultiwallpaper and what we want to test: the background will be scaled except when the resolution matches the 2560x1440 default backgrounds. https://bugzilla.gnome.org/show_bug.cgi?id=735385
831 lines
31 KiB
JavaScript
831 lines
31 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
const GDesktopEnums = imports.gi.GDesktopEnums;
|
|
const Gio = imports.gi.Gio;
|
|
const GLib = imports.gi.GLib;
|
|
const GnomeDesktop = imports.gi.GnomeDesktop;
|
|
const Lang = imports.lang;
|
|
const Meta = imports.gi.Meta;
|
|
const Signals = imports.signals;
|
|
|
|
const Main = imports.ui.main;
|
|
const Params = imports.misc.params;
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
const BACKGROUND_SCHEMA = 'org.gnome.desktop.background';
|
|
const PRIMARY_COLOR_KEY = 'primary-color';
|
|
const SECONDARY_COLOR_KEY = 'secondary-color';
|
|
const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
|
|
const BACKGROUND_STYLE_KEY = 'picture-options';
|
|
const PICTURE_OPACITY_KEY = 'picture-opacity';
|
|
const PICTURE_URI_KEY = 'picture-uri';
|
|
|
|
const FADE_ANIMATION_TIME = 1.0;
|
|
|
|
// These parameters affect how often we redraw.
|
|
// The first is how different (percent crossfaded) the slide show
|
|
// has to look before redrawing and the second is the minimum
|
|
// frequency (in seconds) we're willing to wake up
|
|
const ANIMATION_OPACITY_STEP_INCREMENT = 4.0;
|
|
const ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
|
|
|
|
let _backgroundCache = null;
|
|
|
|
const BackgroundCache = new Lang.Class({
|
|
Name: 'BackgroundCache',
|
|
|
|
_init: function() {
|
|
this._patterns = [];
|
|
this._images = [];
|
|
this._pendingFileLoads = [];
|
|
this._fileMonitors = {};
|
|
},
|
|
|
|
getPatternContent: function(params) {
|
|
params = Params.parse(params, { monitorIndex: 0,
|
|
color: null,
|
|
secondColor: null,
|
|
shadingType: null,
|
|
effects: Meta.BackgroundEffects.NONE });
|
|
|
|
let content = null;
|
|
|
|
let candidateContent = null;
|
|
for (let i = 0; i < this._patterns.length; i++) {
|
|
if (this._patterns[i].get_shading() != params.shadingType)
|
|
continue;
|
|
|
|
if (!params.color.equal(this._patterns[i].get_color()))
|
|
continue;
|
|
|
|
if (params.shadingType != GDesktopEnums.BackgroundShading.SOLID &&
|
|
!params.secondColor.equal(this._patterns[i].get_second_color()))
|
|
continue;
|
|
|
|
candidateContent = this._patterns[i];
|
|
|
|
if (params.effects != this._patterns[i].effects)
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
if (candidateContent) {
|
|
content = candidateContent.copy(params.monitorIndex, params.effects);
|
|
} else {
|
|
content = new Meta.Background({ meta_screen: global.screen,
|
|
monitor: params.monitorIndex,
|
|
effects: params.effects });
|
|
|
|
if (params.shadingType == GDesktopEnums.BackgroundShading.SOLID) {
|
|
content.load_color(params.color);
|
|
} else {
|
|
content.load_gradient(params.shadingType, params.color, params.secondColor);
|
|
}
|
|
}
|
|
|
|
this._patterns.push(content);
|
|
return content;
|
|
},
|
|
|
|
_monitorFile: function(filename) {
|
|
if (this._fileMonitors[filename])
|
|
return;
|
|
|
|
let file = Gio.File.new_for_path(filename);
|
|
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
|
|
|
|
let signalId = monitor.connect('changed',
|
|
Lang.bind(this, function() {
|
|
for (let i = 0; i < this._images.length; i++) {
|
|
if (this._images[i].get_filename() == filename)
|
|
this._images.splice(i, 1);
|
|
}
|
|
|
|
monitor.disconnect(signalId);
|
|
|
|
this.emit('file-changed', filename);
|
|
}));
|
|
|
|
this._fileMonitors[filename] = monitor;
|
|
},
|
|
|
|
_removeContent: function(contentList, content) {
|
|
let index = contentList.indexOf(content);
|
|
if (index < 0)
|
|
throw new Error("Trying to remove invalid content: " + content);
|
|
contentList.splice(index, 1);
|
|
},
|
|
|
|
removePatternContent: function(content) {
|
|
this._removeContent(this._patterns, content);
|
|
},
|
|
|
|
removeImageContent: function(content) {
|
|
let filename = content.get_filename();
|
|
|
|
let hasOtherUsers = this._images.some(function(content) { return filename == content.get_filename(); });
|
|
if (!hasOtherUsers)
|
|
delete this._fileMonitors[filename];
|
|
|
|
this._removeContent(this._images, content);
|
|
},
|
|
|
|
_attachCallerToFileLoad: function(caller, fileLoad) {
|
|
fileLoad.callers.push(caller);
|
|
|
|
if (!caller.cancellable)
|
|
return;
|
|
|
|
caller.cancellable.connect(Lang.bind(this, function() {
|
|
let idx = fileLoad.callers.indexOf(caller);
|
|
fileLoad.callers.splice(idx, 1);
|
|
|
|
if (fileLoad.callers.length == 0) {
|
|
fileLoad.cancellable.cancel();
|
|
|
|
let idx = this._pendingFileLoads.indexOf(fileLoad);
|
|
this._pendingFileLoads.splice(idx, 1);
|
|
}
|
|
}));
|
|
},
|
|
|
|
_loadImageContent: function(params) {
|
|
params = Params.parse(params, { monitorIndex: 0,
|
|
style: null,
|
|
filename: null,
|
|
effects: Meta.BackgroundEffects.NONE,
|
|
cancellable: null,
|
|
onFinished: null });
|
|
|
|
let caller = { monitorIndex: params.monitorIndex,
|
|
effects: params.effects,
|
|
cancellable: params.cancellable,
|
|
onFinished: params.onFinished };
|
|
|
|
for (let i = 0; i < this._pendingFileLoads.length; i++) {
|
|
let fileLoad = this._pendingFileLoads[i];
|
|
|
|
if (fileLoad.filename == params.filename &&
|
|
fileLoad.style == params.style) {
|
|
this._attachCallerToFileLoad(caller, fileLoad);
|
|
return;
|
|
}
|
|
}
|
|
|
|
let fileLoad = { filename: params.filename,
|
|
style: params.style,
|
|
cancellable: new Gio.Cancellable(),
|
|
callers: [] };
|
|
this._attachCallerToFileLoad(caller, fileLoad);
|
|
|
|
let content = new Meta.Background({ meta_screen: global.screen });
|
|
|
|
content.load_file_async(params.filename,
|
|
params.style,
|
|
params.cancellable,
|
|
Lang.bind(this,
|
|
function(object, result) {
|
|
try {
|
|
content.load_file_finish(result);
|
|
|
|
this._monitorFile(params.filename);
|
|
} catch(e) {
|
|
content = null;
|
|
}
|
|
|
|
for (let i = 0; i < fileLoad.callers.length; i++) {
|
|
let caller = fileLoad.callers[i];
|
|
if (caller.onFinished) {
|
|
let newContent;
|
|
|
|
if (content) {
|
|
newContent = content.copy(caller.monitorIndex, caller.effects);
|
|
this._images.push(newContent);
|
|
}
|
|
|
|
caller.onFinished(newContent);
|
|
}
|
|
}
|
|
|
|
let idx = this._pendingFileLoads.indexOf(fileLoad);
|
|
this._pendingFileLoads.splice(idx, 1);
|
|
}));
|
|
},
|
|
|
|
getImageContent: function(params) {
|
|
params = Params.parse(params, { monitorIndex: 0,
|
|
style: null,
|
|
filename: null,
|
|
effects: Meta.BackgroundEffects.NONE,
|
|
cancellable: null,
|
|
onFinished: null });
|
|
|
|
let content = null;
|
|
|
|
let candidateContent = null;
|
|
for (let i = 0; i < this._images.length; i++) {
|
|
if (this._images[i].get_style() != params.style)
|
|
continue;
|
|
|
|
if (this._images[i].get_filename() != params.filename)
|
|
continue;
|
|
|
|
if (params.style == GDesktopEnums.BackgroundStyle.SPANNED &&
|
|
this._images[i].monitor != params.monitorIndex)
|
|
continue;
|
|
|
|
candidateContent = this._images[i];
|
|
|
|
if (params.effects != this._images[i].effects)
|
|
continue;
|
|
|
|
break;
|
|
}
|
|
|
|
if (candidateContent) {
|
|
content = candidateContent.copy(params.monitorIndex, params.effects);
|
|
|
|
if (params.cancellable && params.cancellable.is_cancelled())
|
|
content = null;
|
|
else
|
|
this._images.push(content);
|
|
|
|
if (params.onFinished)
|
|
params.onFinished(content);
|
|
} else {
|
|
this._loadImageContent({ filename: params.filename,
|
|
style: params.style,
|
|
effects: params.effects,
|
|
monitorIndex: params.monitorIndex,
|
|
cancellable: params.cancellable,
|
|
onFinished: params.onFinished });
|
|
|
|
}
|
|
},
|
|
|
|
getAnimation: function(params) {
|
|
params = Params.parse(params, { filename: null,
|
|
onLoaded: null });
|
|
|
|
if (this._animationFilename == params.filename) {
|
|
if (params.onLoaded) {
|
|
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
|
params.onLoaded(this._animation);
|
|
return GLib.SOURCE_REMOVE;
|
|
}));
|
|
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
|
|
}
|
|
}
|
|
|
|
let animation = new Animation({ filename: params.filename });
|
|
|
|
animation.load(Lang.bind(this, function() {
|
|
this._monitorFile(params.filename);
|
|
this._animationFilename = params.filename;
|
|
this._animation = animation;
|
|
|
|
if (params.onLoaded) {
|
|
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
|
params.onLoaded(this._animation);
|
|
return GLib.SOURCE_REMOVE;
|
|
}));
|
|
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
|
|
}
|
|
}));
|
|
}
|
|
});
|
|
Signals.addSignalMethods(BackgroundCache.prototype);
|
|
|
|
function getBackgroundCache() {
|
|
if (!_backgroundCache)
|
|
_backgroundCache = new BackgroundCache();
|
|
return _backgroundCache;
|
|
}
|
|
|
|
const Background = new Lang.Class({
|
|
Name: 'Background',
|
|
|
|
_init: function(params) {
|
|
params = Params.parse(params, { monitorIndex: 0,
|
|
layoutManager: Main.layoutManager,
|
|
effects: Meta.BackgroundEffects.NONE,
|
|
settings: null,
|
|
overrideImage: null });
|
|
this.actor = new Meta.BackgroundGroup();
|
|
this.actor._delegate = this;
|
|
|
|
this._destroySignalId = this.actor.connect('destroy',
|
|
Lang.bind(this, this._destroy));
|
|
|
|
this._settings = params.settings;
|
|
this._overrideImage = params.overrideImage;
|
|
this._monitorIndex = params.monitorIndex;
|
|
this._layoutManager = params.layoutManager;
|
|
this._effects = params.effects;
|
|
this._fileWatches = {};
|
|
this._pattern = null;
|
|
// contains a single image for static backgrounds and
|
|
// two images (from and to) for slide shows
|
|
this._images = {};
|
|
|
|
this._brightness = 1.0;
|
|
this._vignetteSharpness = 0.2;
|
|
this._cancellable = new Gio.Cancellable();
|
|
this.isLoaded = false;
|
|
|
|
this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
|
|
this.emit('changed');
|
|
}));
|
|
|
|
this._load();
|
|
},
|
|
|
|
_destroy: function() {
|
|
this._cancellable.cancel();
|
|
|
|
if (this._updateAnimationTimeoutId) {
|
|
GLib.source_remove (this._updateAnimationTimeoutId);
|
|
this._updateAnimationTimeoutId = 0;
|
|
}
|
|
|
|
let i;
|
|
let keys = Object.keys(this._fileWatches);
|
|
for (i = 0; i < keys.length; i++) {
|
|
this._cache.disconnect(this._fileWatches[keys[i]]);
|
|
}
|
|
this._fileWatches = null;
|
|
|
|
if (this._pattern) {
|
|
if (this._pattern.content)
|
|
this._cache.removePatternContent(this._pattern.content);
|
|
|
|
this._pattern.destroy();
|
|
this._pattern = null;
|
|
}
|
|
|
|
keys = Object.keys(this._images);
|
|
for (i = 0; i < keys.length; i++) {
|
|
let actor = this._images[keys[i]];
|
|
|
|
if (actor.content)
|
|
this._cache.removeImageContent(actor.content);
|
|
|
|
actor.destroy();
|
|
this._images[keys[i]] = null;
|
|
}
|
|
|
|
this.actor.disconnect(this._destroySignalId);
|
|
this._destroySignalId = 0;
|
|
|
|
if (this._settingsChangedSignalId != 0)
|
|
this._settings.disconnect(this._settingsChangedSignalId);
|
|
this._settingsChangedSignalId = 0;
|
|
},
|
|
|
|
_setLoaded: function() {
|
|
if (this.isLoaded)
|
|
return;
|
|
|
|
this.isLoaded = true;
|
|
|
|
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
|
this.emit('loaded');
|
|
return GLib.SOURCE_REMOVE;
|
|
}));
|
|
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
|
|
},
|
|
|
|
_loadPattern: function() {
|
|
let colorString, res, color, secondColor;
|
|
|
|
colorString = this._settings.get_string(PRIMARY_COLOR_KEY);
|
|
[res, color] = Clutter.Color.from_string(colorString);
|
|
colorString = this._settings.get_string(SECONDARY_COLOR_KEY);
|
|
[res, secondColor] = Clutter.Color.from_string(colorString);
|
|
|
|
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
|
|
|
|
let content = this._cache.getPatternContent({ monitorIndex: this._monitorIndex,
|
|
effects: this._effects,
|
|
color: color,
|
|
secondColor: secondColor,
|
|
shadingType: shadingType });
|
|
|
|
this._pattern = new Meta.BackgroundActor();
|
|
this.actor.add_child(this._pattern);
|
|
|
|
this._pattern.content = content;
|
|
},
|
|
|
|
_watchCacheFile: function(filename) {
|
|
if (this._fileWatches[filename])
|
|
return;
|
|
|
|
let signalId = this._cache.connect('file-changed',
|
|
Lang.bind(this, function(cache, changedFile) {
|
|
if (changedFile == filename) {
|
|
this.emit('changed');
|
|
}
|
|
}));
|
|
this._fileWatches[filename] = signalId;
|
|
},
|
|
|
|
_ensureImage: function(index) {
|
|
if (this._images[index])
|
|
return;
|
|
|
|
let actor = new Meta.BackgroundActor();
|
|
|
|
// The background pattern is the first actor in
|
|
// the group, and all images should be above that.
|
|
this.actor.insert_child_at_index(actor, index + 1);
|
|
this._images[index] = actor;
|
|
},
|
|
|
|
_updateImage: function(index, content, filename) {
|
|
content.brightness = this._brightness;
|
|
content.vignette_sharpness = this._vignetteSharpness;
|
|
|
|
let image = this._images[index];
|
|
if (image.content)
|
|
this._cache.removeImageContent(image.content);
|
|
image.content = content;
|
|
this._watchCacheFile(filename);
|
|
},
|
|
|
|
_updateAnimationProgress: function() {
|
|
if (this._images[1])
|
|
this._images[1].opacity = this._animation.transitionProgress * 255;
|
|
|
|
this._queueUpdateAnimation();
|
|
},
|
|
|
|
_updateAnimation: function() {
|
|
this._updateAnimationTimeoutId = 0;
|
|
|
|
this._animation.update(this._layoutManager.monitors[this._monitorIndex]);
|
|
let files = this._animation.keyFrameFiles;
|
|
|
|
if (files.length == 0) {
|
|
this._setLoaded();
|
|
this._queueUpdateAnimation();
|
|
return;
|
|
}
|
|
|
|
let numPendingImages = files.length;
|
|
for (let i = 0; i < files.length; i++) {
|
|
if (this._images[i] && this._images[i].content &&
|
|
this._images[i].content.get_filename() == files[i]) {
|
|
|
|
numPendingImages--;
|
|
if (numPendingImages == 0)
|
|
this._updateAnimationProgress();
|
|
continue;
|
|
}
|
|
this._cache.getImageContent({ monitorIndex: this._monitorIndex,
|
|
effects: this._effects,
|
|
style: this._style,
|
|
filename: files[i],
|
|
cancellable: this._cancellable,
|
|
onFinished: Lang.bind(this, function(content, i) {
|
|
numPendingImages--;
|
|
|
|
if (!content) {
|
|
this._setLoaded();
|
|
if (numPendingImages == 0)
|
|
this._updateAnimationProgress();
|
|
return;
|
|
}
|
|
|
|
this._ensureImage(i);
|
|
this._updateImage(i, content, files[i]);
|
|
|
|
if (numPendingImages == 0) {
|
|
this._setLoaded();
|
|
this._updateAnimationProgress();
|
|
}
|
|
}, i)
|
|
});
|
|
}
|
|
},
|
|
|
|
_queueUpdateAnimation: function() {
|
|
if (this._updateAnimationTimeoutId != 0)
|
|
return;
|
|
|
|
if (!this._cancellable || this._cancellable.is_cancelled())
|
|
return;
|
|
|
|
if (!this._animation.transitionDuration)
|
|
return;
|
|
|
|
let nSteps = 255 / ANIMATION_OPACITY_STEP_INCREMENT;
|
|
let timePerStep = (this._animation.transitionDuration * 1000) / nSteps;
|
|
|
|
let interval = Math.max(ANIMATION_MIN_WAKEUP_INTERVAL * 1000,
|
|
timePerStep);
|
|
|
|
if (interval > GLib.MAXUINT32)
|
|
return;
|
|
|
|
this._updateAnimationTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
|
|
interval,
|
|
Lang.bind(this, function() {
|
|
this._updateAnimationTimeoutId = 0;
|
|
this._updateAnimation();
|
|
return GLib.SOURCE_REMOVE;
|
|
}));
|
|
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
|
|
},
|
|
|
|
_loadAnimation: function(filename) {
|
|
this._cache.getAnimation({ filename: filename,
|
|
onLoaded: Lang.bind(this, function(animation) {
|
|
this._animation = animation;
|
|
|
|
if (!this._animation || this._cancellable.is_cancelled()) {
|
|
this._setLoaded();
|
|
return;
|
|
}
|
|
|
|
this._updateAnimation();
|
|
this._watchCacheFile(filename);
|
|
})
|
|
});
|
|
},
|
|
|
|
_loadImage: function(filename) {
|
|
this._cache.getImageContent({ monitorIndex: this._monitorIndex,
|
|
effects: this._effects,
|
|
style: this._style,
|
|
filename: filename,
|
|
cancellable: this._cancellable,
|
|
onFinished: Lang.bind(this, function(content) {
|
|
if (content) {
|
|
this._ensureImage(0);
|
|
this._updateImage(0, content, filename);
|
|
}
|
|
this._setLoaded();
|
|
})
|
|
});
|
|
},
|
|
|
|
_loadFile: function(filename) {
|
|
if (filename.endsWith('.xml'))
|
|
this._loadAnimation(filename);
|
|
else
|
|
this._loadImage(filename);
|
|
},
|
|
|
|
_load: function () {
|
|
this._cache = getBackgroundCache();
|
|
|
|
this._loadPattern();
|
|
|
|
let filename;
|
|
if (this._overrideImage != null) {
|
|
filename = this._overrideImage;
|
|
this._style = GDesktopEnums.BackgroundStyle.ZOOM; // Hardcode
|
|
} else {
|
|
this._style = this._settings.get_enum(BACKGROUND_STYLE_KEY);
|
|
if (this._style == GDesktopEnums.BackgroundStyle.NONE) {
|
|
this._setLoaded();
|
|
return;
|
|
}
|
|
|
|
let uri = this._settings.get_string(PICTURE_URI_KEY);
|
|
if (GLib.uri_parse_scheme(uri) != null)
|
|
filename = Gio.File.new_for_uri(uri).get_path();
|
|
else
|
|
filename = uri;
|
|
}
|
|
|
|
if (!filename) {
|
|
this._setLoaded();
|
|
return;
|
|
}
|
|
|
|
this._loadFile(filename);
|
|
},
|
|
|
|
get brightness() {
|
|
return this._brightness;
|
|
},
|
|
|
|
set brightness(factor) {
|
|
this._brightness = factor;
|
|
if (this._pattern && this._pattern.content)
|
|
this._pattern.content.brightness = factor;
|
|
|
|
let keys = Object.keys(this._images);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
let image = this._images[keys[i]];
|
|
if (image && image.content)
|
|
image.content.brightness = factor;
|
|
}
|
|
},
|
|
|
|
get vignetteSharpness() {
|
|
return this._vignetteSharpness;
|
|
},
|
|
|
|
set vignetteSharpness(sharpness) {
|
|
this._vignetteSharpness = sharpness;
|
|
if (this._pattern && this._pattern.content)
|
|
this._pattern.content.vignette_sharpness = sharpness;
|
|
|
|
let keys = Object.keys(this._images);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
let image = this._images[keys[i]];
|
|
if (image && image.content)
|
|
image.content.vignette_sharpness = sharpness;
|
|
}
|
|
}
|
|
});
|
|
Signals.addSignalMethods(Background.prototype);
|
|
|
|
const SystemBackground = new Lang.Class({
|
|
Name: 'SystemBackground',
|
|
|
|
_init: function() {
|
|
this._cache = getBackgroundCache();
|
|
this.actor = new Meta.BackgroundActor();
|
|
|
|
this._cache.getImageContent({ style: GDesktopEnums.BackgroundStyle.WALLPAPER,
|
|
filename: global.datadir + '/theme/noise-texture.png',
|
|
effects: Meta.BackgroundEffects.NONE,
|
|
onFinished: Lang.bind(this, function(content) {
|
|
this.actor.content = content;
|
|
this.emit('loaded');
|
|
})
|
|
});
|
|
|
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
|
},
|
|
|
|
_onDestroy: function() {
|
|
let content = this.actor.content;
|
|
|
|
if (content)
|
|
this._cache.removeImageContent(content);
|
|
},
|
|
});
|
|
Signals.addSignalMethods(SystemBackground.prototype);
|
|
|
|
const Animation = new Lang.Class({
|
|
Name: 'Animation',
|
|
|
|
_init: function(params) {
|
|
params = Params.parse(params, { filename: null });
|
|
|
|
this.filename = params.filename;
|
|
this.keyFrameFiles = [];
|
|
this.transitionProgress = 0.0;
|
|
this.transitionDuration = 0.0;
|
|
this.loaded = false;
|
|
},
|
|
|
|
load: function(callback) {
|
|
let file = Gio.File.new_for_path(this.filename);
|
|
|
|
this._show = new GnomeDesktop.BGSlideShow({ filename: this.filename });
|
|
|
|
this._show.load_async(null,
|
|
Lang.bind(this,
|
|
function(object, result) {
|
|
this.loaded = true;
|
|
if (callback)
|
|
callback();
|
|
}));
|
|
},
|
|
|
|
update: function(monitor) {
|
|
this.keyFrameFiles = [];
|
|
|
|
if (!this._show)
|
|
return;
|
|
|
|
if (this._show.get_num_slides() < 1)
|
|
return;
|
|
|
|
let [progress, duration, isFixed, file1, file2] = this._show.get_current_slide(monitor.width, monitor.height);
|
|
|
|
this.transitionDuration = duration;
|
|
this.transitionProgress = progress;
|
|
|
|
if (file1)
|
|
this.keyFrameFiles.push(file1);
|
|
|
|
if (file2)
|
|
this.keyFrameFiles.push(file2);
|
|
},
|
|
});
|
|
Signals.addSignalMethods(Animation.prototype);
|
|
|
|
const BackgroundManager = new Lang.Class({
|
|
Name: 'BackgroundManager',
|
|
|
|
_init: function(params) {
|
|
params = Params.parse(params, { container: null,
|
|
layoutManager: Main.layoutManager,
|
|
monitorIndex: null,
|
|
effects: Meta.BackgroundEffects.NONE,
|
|
controlPosition: true,
|
|
settingsSchema: BACKGROUND_SCHEMA });
|
|
|
|
// Allow override the background image setting for performance testing
|
|
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
|
|
this._settings = new Gio.Settings({ schema_id: params.settingsSchema });
|
|
this._container = params.container;
|
|
this._layoutManager = params.layoutManager;
|
|
this._effects = params.effects;
|
|
this._monitorIndex = params.monitorIndex;
|
|
this._controlPosition = params.controlPosition;
|
|
|
|
this.background = this._createBackground();
|
|
this._newBackground = null;
|
|
},
|
|
|
|
destroy: function() {
|
|
if (this._newBackground) {
|
|
this._newBackground.actor.destroy();
|
|
this._newBackground = null;
|
|
}
|
|
|
|
if (this.background) {
|
|
this.background.actor.destroy();
|
|
this.background = null;
|
|
}
|
|
},
|
|
|
|
_updateBackground: function() {
|
|
let newBackground = this._createBackground();
|
|
newBackground.vignetteSharpness = this.background.vignetteSharpness;
|
|
newBackground.brightness = this.background.brightness;
|
|
newBackground.visible = this.background.visible;
|
|
|
|
newBackground.loadedSignalId = newBackground.connect('loaded',
|
|
Lang.bind(this, function() {
|
|
newBackground.disconnect(newBackground.loadedSignalId);
|
|
newBackground.loadedSignalId = 0;
|
|
|
|
if (this._newBackground != newBackground) {
|
|
/* Not interesting, we queued another load */
|
|
newBackground.actor.destroy();
|
|
return;
|
|
}
|
|
|
|
Tweener.addTween(this.background.actor,
|
|
{ opacity: 0,
|
|
time: FADE_ANIMATION_TIME,
|
|
transition: 'easeOutQuad',
|
|
onComplete: Lang.bind(this, function() {
|
|
this.background.actor.destroy();
|
|
this.background = newBackground;
|
|
this._newBackground = null;
|
|
|
|
this.emit('changed');
|
|
})
|
|
});
|
|
}));
|
|
|
|
this._newBackground = newBackground;
|
|
},
|
|
|
|
_createBackground: function() {
|
|
let background = new Background({ monitorIndex: this._monitorIndex,
|
|
layoutManager: this._layoutManager,
|
|
effects: this._effects,
|
|
settings: this._settings,
|
|
overrideImage: this._overrideImage });
|
|
this._container.add_child(background.actor);
|
|
|
|
let monitor = this._layoutManager.monitors[this._monitorIndex];
|
|
|
|
background.actor.set_size(monitor.width, monitor.height);
|
|
if (this._controlPosition) {
|
|
background.actor.set_position(monitor.x, monitor.y);
|
|
background.actor.lower_bottom();
|
|
}
|
|
|
|
background.changeSignalId = background.connect('changed', Lang.bind(this, function() {
|
|
background.disconnect(background.changeSignalId);
|
|
background.changeSignalId = 0;
|
|
this._updateBackground();
|
|
}));
|
|
|
|
background.actor.connect('destroy', Lang.bind(this, function() {
|
|
if (background.changeSignalId)
|
|
background.disconnect(background.changeSignalId);
|
|
|
|
if (background.loadedSignalId)
|
|
background.disconnect(background.loadedSignalId);
|
|
}));
|
|
|
|
return background;
|
|
},
|
|
});
|
|
Signals.addSignalMethods(BackgroundManager.prototype);
|