theme: Search in versioned directories

We support third party themes, via the "stylesheetName" property of a
mode's json files. However, our external CSS API is not completely
stable. If a third party theme wants to work on multiple gnome-shell
versions - for example because it is shipped as a Flatpak or a Snap - it
is not possible to ensure that a theme corresponding to the running
gnome-shell version is loaded.

GTK+ loads themes from versioned directories, search backwards from the
current version. Let's do the same in gnome-shell too. Then a downstream
theme can be shipped in $datadir/gnome-shell/3.28/theme/.

We keep searching all of the current paths. Additionally, the default
case where we look for the 'gnome' theme as a resource in the binary
continues to be the default so there are no additional lookups for users
of this theme.
This commit is contained in:
Iain Lane 2018-06-28 11:14:54 +01:00
parent 5fe349d5ba
commit 9ab35786f6

View File

@ -14,6 +14,7 @@ const St = imports.gi.St;
const AccessDialog = imports.ui.accessDialog; const AccessDialog = imports.ui.accessDialog;
const AudioDeviceSelection = imports.ui.audioDeviceSelection; const AudioDeviceSelection = imports.ui.audioDeviceSelection;
const Components = imports.ui.components; const Components = imports.ui.components;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const EndSessionDialog = imports.ui.endSessionDialog; const EndSessionDialog = imports.ui.endSessionDialog;
const Environment = imports.ui.environment; const Environment = imports.ui.environment;
@ -249,26 +250,61 @@ function _initializeUI() {
}); });
} }
function _findThemeDirByVersion(dir, major, minor, name) {
let path;
let stylesheet;
let subpath;
/* Don't search back to before we introduced this support */
let max_minor = (major == 3) ? 28 : 0;
for (let i = minor; i >= max_minor; i = i - 2) {
subpath = major + '.' + i;
path = GLib.build_filenamev([dir, 'gnome-shell', subpath, 'theme', name]);
stylesheet = Gio.file_new_for_path(path);
log('Checking for ' + path);
if (stylesheet.query_exists(null)) {
log('Using ' + path);
return stylesheet;
}
}
path = GLib.build_filenamev([dir, 'gnome-shell', 'theme', name]);
stylesheet = Gio.file_new_for_path(path);
if (stylesheet.query_exists(null)) {
log('Using unversioned' + path);
return stylesheet;
}
return null;
}
function _getStylesheet(name) { function _getStylesheet(name) {
let stylesheet; let stylesheet;
let [major, minor] = Config.PACKAGE_VERSION.split('.');
// Directories are versioned according to the stable version
if ((minor % 2) == 1)
minor++;
stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + name); stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + name);
if (stylesheet.query_exists(null)) if (stylesheet.query_exists(null)) {
log('Using built-in default theme ' + name)
return stylesheet; return stylesheet;
}
let dataDirs = GLib.get_system_data_dirs(); let dataDirs = GLib.get_system_data_dirs();
for (let i = 0; i < dataDirs.length; i++) { for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'theme', name]); stylesheet = _findThemeDirByVersion(dataDirs[i], major, minor, name)
let stylesheet = Gio.file_new_for_path(path); if (stylesheet != null)
if (stylesheet.query_exists(null))
return stylesheet; return stylesheet;
} }
stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + name); return _findThemeDirByVersion(global.datadir, major, minor, name);
if (stylesheet.query_exists(null))
return stylesheet;
return null;
} }
function _getDefaultStylesheet() { function _getDefaultStylesheet() {