diff --git a/data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml b/data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
new file mode 100644
index 000000000..1e89bbe1d
--- /dev/null
+++ b/data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/data/gnome-shell-dbus-interfaces.gresource.xml b/data/gnome-shell-dbus-interfaces.gresource.xml
index 3352e0dcd..21fdfa949 100644
--- a/data/gnome-shell-dbus-interfaces.gresource.xml
+++ b/data/gnome-shell-dbus-interfaces.gresource.xml
@@ -48,6 +48,7 @@
org.gnome.Shell.Screencast.xml
org.gnome.Shell.Screenshot.xml
org.gnome.Shell.Wacom.PadOsd.xml
+ org.gnome.Shell.WeatherIntegration.xml
org.gnome.Shell.xml
org.Gtk.MountOperationHandler.xml
org.gtk.Notifications.xml
diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in
index 4aca92162..9c3e42c94 100644
--- a/data/org.gnome.shell.gschema.xml.in
+++ b/data/org.gnome.shell.gschema.xml.in
@@ -233,6 +233,25 @@
+
+
+ Automatic location
+
+ Whether to fetch the current location or not
+
+ false
+
+
+
+ Location
+
+ The location for which to show a forecast
+
+ []
+
+
+
diff --git a/js/misc/weather.js b/js/misc/weather.js
index efd8ce82d..4d63d745b 100644
--- a/js/misc/weather.js
+++ b/js/misc/weather.js
@@ -1,10 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const { Geoclue, Gio, GLib, GWeather } = imports.gi;
+const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore;
-const Util = imports.misc.util;
+
+const { loadInterfaceXML } = imports.misc.fileUtils;
+
+const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
+
+const WEATHER_BUS_NAME = 'org.gnome.Weather';
+const WEATHER_OBJECT_PATH = '/org/gnome/Weather';
+const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
+
+const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
// Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@@ -66,17 +75,36 @@ var WeatherClient = class {
this.emit('changed');
});
- this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
- 'org.gnome.Weather');
- this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
- this._weatherAppMon.watchSetting('automatic-location',
- this._onAutomaticLocationChanged.bind(this));
- this._weatherAppMon.watchSetting('locations',
- this._onLocationsChanged.bind(this));
+ this._weatherApp = null;
+ this._weatherProxy = null;
+
+ let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
+ Gio.DBusProxy.new(
+ Gio.DBus.session,
+ Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
+ nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
+ WEATHER_BUS_NAME,
+ WEATHER_OBJECT_PATH,
+ WEATHER_INTEGRATION_IFACE,
+ null,
+ this._onWeatherProxyReady.bind(this));
+
+ this._settings = new Gio.Settings({
+ schema_id: 'org.gnome.shell.weather'
+ });
+ this._settings.connect('changed::automatic-location',
+ this._onAutomaticLocationChanged.bind(this));
+ this._settings.connect('changed::locations',
+ this._onLocationsChanged.bind(this));
+
+ this._appSystem = Shell.AppSystem.get_default();
+ this._appSystem.connect('installed-changed',
+ this._onInstalledChanged.bind(this));
+ this._onInstalledChanged();
}
get available() {
- return this._weatherAppMon.available;
+ return this._weatherApp != null;
}
get loading() {
@@ -92,7 +120,8 @@ var WeatherClient = class {
}
activateApp() {
- this._weatherAppMon.activateApp();
+ if (this._weatherApp)
+ this._weatherApp.activate();
}
update() {
@@ -114,6 +143,37 @@ var WeatherClient = class {
this._weatherAuthorized;
}
+ _onWeatherProxyReady(o, res) {
+ try {
+ this._weatherProxy = Gio.DBusProxy.new_finish(res);
+ } catch (e) {
+ log(`Failed to create GNOME Weather proxy: ${e}`);
+ return;
+ }
+
+ this._weatherProxy.connect('g-properties-changed',
+ this._onWeatherPropertiesChanged.bind(this));
+
+ if (this._weatherProxy.g_owner != null)
+ this._onWeatherPropertiesChanged();
+ }
+
+ _onWeatherPropertiesChanged() {
+ this._settings.set_boolean('automatic-location',
+ this._weatherProxy.AutomaticLocation);
+ this._settings.set_value('locations',
+ new GLib.Variant('av', this._weatherProxy.Locations));
+ }
+
+ _onInstalledChanged() {
+ let hadApp = (this._weatherApp != null);
+ this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
+ let haveApp = (this._weatherApp != null);
+
+ if (hadApp !== haveApp)
+ this.emit('changed');
+ }
+
_loadInfo() {
let id = this._weatherInfo.connect('updated', () => {
this._weatherInfo.disconnect(id);