[gnome-shell] util: Add AppSettingsMonitor
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] util: Add AppSettingsMonitor
- Date: Mon, 27 Feb 2017 19:02:56 +0000 (UTC)
commit b5130c5943de6d0f415493d39dd32e9d4210e20a
Author: Florian Müllner <fmuellner gnome org>
Date: Thu Feb 23 22:50:04 2017 +0100
util: Add AppSettingsMonitor
When integrating with optional components like Clocks, it is not safe
to access their GSettings right after the application became visible
to the AppSystem:
Installation is usually not atomic, so the .desktop file may appear
before the settings schema, in which case Gio will abort due to an
"invalid" schema ID.
To address this, add a small helper class that wraps the settings
access in a safe way.
https://bugzilla.gnome.org/show_bug.cgi?id=766410
js/misc/util.js | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 93 insertions(+), 0 deletions(-)
---
diff --git a/js/misc/util.js b/js/misc/util.js
index 7c6d111..0221e15 100644
--- a/js/misc/util.js
+++ b/js/misc/util.js
@@ -4,6 +4,8 @@ const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@@ -398,3 +400,94 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
time: SCROLL_TIME,
transition: 'easeOutQuad' });
}
+
+const AppSettingsMonitor = new Lang.Class({
+ Name: 'AppSettingsMonitor',
+
+ _init: function(appId, schemaId) {
+ this._appId = appId;
+ this._schemaId = schemaId;
+
+ this._app = null;
+ this._settings = null;
+ this._handlers = [];
+
+ this._schemaSource = Gio.SettingsSchemaSource.get_default();
+
+ this._appSystem = Shell.AppSystem.get_default();
+ this._appSystem.connect('installed-changed',
+ Lang.bind(this, this._onInstalledChanged));
+ this._onInstalledChanged();
+ },
+
+ get available() {
+ return this._app != null && this._settings != null;
+ },
+
+ activateApp: function() {
+ if (this._app)
+ this._app.activate();
+ },
+
+ watchSetting: function(key, callback) {
+ let handler = { id: 0, key: key, callback: callback };
+ this._handlers.push(handler);
+
+ this._connectHandler(handler);
+ },
+
+ _connectHandler: function(handler) {
+ if (!this._settings || handler.id > 0)
+ return;
+
+ handler.id = this._settings.connect('changed::' + handler.key,
+ handler.callback);
+ handler.callback(this._settings, handler.key);
+ },
+
+ _disconnectHandler: function(handler) {
+ if (this._settings && handler.id > 0)
+ this._settings.disconnect(handler.id);
+ handler.id = 0;
+ },
+
+ _onInstalledChanged: function() {
+ let hadApp = (this._app != null);
+ this._app = this._appSystem.lookup_app(this._appId);
+ let haveApp = (this._app != null);
+
+ if (hadApp == haveApp)
+ return;
+
+ if (haveApp)
+ this._checkSettings();
+ else
+ this._setSettings(null);
+ },
+
+ _setSettings(settings) {
+ this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
+
+ let hadSettings = (this._settings != null);
+ this._settings = settings;
+ let haveSettings = (this._settings != null);
+
+ this._handlers.forEach((handler) => { this._connectHandler(handler); });
+
+ if (hadSettings != haveSettings)
+ this.emit('available-changed');
+ },
+
+ _checkSettings: function() {
+ let schema = this._schemaSource.lookup(this._schemaId, true);
+ if (schema) {
+ this._setSettings(new Gio.Settings({ settings_schema: schema }));
+ } else if (this._app) {
+ Mainloop.timeout_add_seconds(1, () => {
+ this._checkSettings();
+ return GLib.SOURCE_REMOVE;
+ });
+ }
+ }
+});
+Signals.addSignalMethods(AppSettingsMonitor.prototype);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]