From 9ab35786f6bfbedcb9738d855a82508c95e54cc7 Mon Sep 17 00:00:00 2001 From: Iain Lane Date: Thu, 28 Jun 2018 11:14:54 +0100 Subject: [PATCH] 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. --- js/ui/main.js | 54 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/js/ui/main.js b/js/ui/main.js index d86cf9e81..088cd48bd 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -14,6 +14,7 @@ const St = imports.gi.St; const AccessDialog = imports.ui.accessDialog; const AudioDeviceSelection = imports.ui.audioDeviceSelection; const Components = imports.ui.components; +const Config = imports.misc.config; const CtrlAltTab = imports.ui.ctrlAltTab; const EndSessionDialog = imports.ui.endSessionDialog; 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) { 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); - if (stylesheet.query_exists(null)) + if (stylesheet.query_exists(null)) { + log('Using built-in default theme ' + name) return stylesheet; + } let dataDirs = GLib.get_system_data_dirs(); for (let i = 0; i < dataDirs.length; i++) { - let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'theme', name]); - let stylesheet = Gio.file_new_for_path(path); - if (stylesheet.query_exists(null)) + stylesheet = _findThemeDirByVersion(dataDirs[i], major, minor, name) + if (stylesheet != null) return stylesheet; } - stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + name); - if (stylesheet.query_exists(null)) - return stylesheet; - - return null; + return _findThemeDirByVersion(global.datadir, major, minor, name); } function _getDefaultStylesheet() {