[gnome-shell/gnome-3-8] background: fix asynchronous management of background loading operations
- From: Lionel Landwerlin <llandwerlin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/gnome-3-8] background: fix asynchronous management of background loading operations
- Date: Wed, 3 Jul 2013 16:03:28 +0000 (UTC)
commit 1020d8a0f8523a04d8336b1348388b8b242e414f
Author: Lionel Landwerlin <llandwerlin gmail com>
Date: Mon Jun 24 19:13:05 2013 +0100
background: fix asynchronous management of background loading operations
This fixes a blue background being drawn when switching the monitors
configuration using hardware keys
(clone/multimonitor/external/internal).
The problem is that the shell gather all background loading requests
under the same meta_background_load_file_async call using one
GCancellable (the first one to come). So when the shell receives a
batch of 12 or so XRandr events, it creates 12 new background managers
which end up trying to load 12 times the same background picture. All
of these requests are batched into the same
meta_background_load_file_async using the first GCancellable received
on the first request. Unfortunately, when the first request is
cancelled by the following event indicating a new monitor setup, all
of the background picture requests are dropped on the floor, and
nothing gets loaded (hence the blue screen background).
https://bugzilla.gnome.org/show_bug.cgi?id=703001
js/ui/background.js | 69 ++++++++++++++++++++++++++++++++------------------
1 files changed, 44 insertions(+), 25 deletions(-)
---
diff --git a/js/ui/background.js b/js/ui/background.js
index 0e9c3aa..f2ffce8 100644
--- a/js/ui/background.js
+++ b/js/ui/background.js
@@ -142,33 +142,40 @@ const BackgroundCache = new Lang.Class({
cancellable: null,
onFinished: null });
- for (let i = 0; i < this._pendingFileLoads.length; i++) {
- if (this._pendingFileLoads[i].filename == params.filename &&
- this._pendingFileLoads[i].style == params.style) {
- this._pendingFileLoads[i].callers.push({ shouldCopy: true,
- monitorIndex: params.monitorIndex,
- effects: params.effects,
- onFinished: params.onFinished });
- return;
- }
+ let fileLoad = { filename: params.filename,
+ style: params.style,
+ shouldCopy: false,
+ monitorIndex: params.monitorIndex,
+ effects: params.effects,
+ onFinished: params.onFinished,
+ cancellable: new Gio.Cancellable(), };
+ this._pendingFileLoads.push(fileLoad);
+
+ if (params.cancellable) {
+ params.cancellable.connect(Lang.bind(this, function(c) {
+ fileLoad.cancellable.cancel();
+ }));
}
- this._pendingFileLoads.push({ filename: params.filename,
- style: params.style,
- callers: [{ shouldCopy: false,
- monitorIndex: params.monitorIndex,
- effects: params.effects,
- onFinished: params.onFinished }] });
-
let content = new Meta.Background({ meta_screen: global.screen,
monitor: params.monitorIndex,
effects: params.effects });
content.load_file_async(params.filename,
params.style,
- params.cancellable,
+ fileLoad.cancellable,
Lang.bind(this,
function(object, result) {
+ if (fileLoad.cancellable.is_cancelled()) {
+ if (params.cancellable &&
params.cancellable.is_cancelled()) {
+ if (params.onFinished)
+ params.onFinished(null);
+ this._removePendingFileLoad(fileLoad);
+ return;
+ }
+ return;
+ }
+
try {
content.load_file_finish(result);
@@ -178,22 +185,25 @@ const BackgroundCache = new Lang.Class({
content = null;
}
+ let needsCopy = false;
for (let i = 0; i < this._pendingFileLoads.length; i++) {
let pendingLoad = this._pendingFileLoads[i];
if (pendingLoad.filename != params.filename ||
pendingLoad.style != params.style)
continue;
- for (let j = 0; j < pendingLoad.callers.length; j++) {
- if (pendingLoad.callers[j].onFinished) {
- if (content && pendingLoad.callers[j].shouldCopy) {
- content =
object.copy(pendingLoad.callers[j].monitorIndex,
-
pendingLoad.callers[j].effects);
-
- }
+ if (pendingLoad.cancellable.is_cancelled())
+ continue;
- pendingLoad.callers[j].onFinished(content);
+ pendingLoad.cancellable.cancel();
+ if (pendingLoad.onFinished) {
+ if (content && needsCopy) {
+ content = object.copy(pendingLoad.monitorIndex,
+ pendingLoad.effects);
}
+
+ needsCopy = true;
+ pendingLoad.onFinished(content);
}
this._pendingFileLoads.splice(i, 1);
@@ -201,6 +211,15 @@ const BackgroundCache = new Lang.Class({
}));
},
+ _removePendingFileLoad: function(fileLoad) {
+ for (let i = 0; i < this._pendingFileLoads.length; i++) {
+ if (this._pendingFileLoads[i].cancellable == fileLoad.cancellable) {
+ this._pendingFileLoads.splice(i, 1);
+ break;
+ }
+ }
+ },
+
getImageContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
style: null,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]