Compare commits

..

12 Commits

Author SHA1 Message Date
59724c5dd5 Bump version to 3.14.2
Update NEWS.
2014-11-12 19:30:14 +01:00
3bb500fed4 viewSelector: Hide workspace page after animating to app picker
WorkspacesDisplay relies on being hidden to disable workspace switches
by scrolling or panning. Usually viewSelector will hide the previous
page on page switch, but we currently miss the case when opening the
overview at the app picker, where the workspaces page is still shown
for the transition, but never hidden.
Fix this by calling hide() in addition to setting the opacity to 0 at
the end of the overview animation.

https://bugzilla.gnome.org/show_bug.cgi?id=737534
2014-11-12 19:19:31 +01:00
dcd3945bb7 Move style updates in AppIcon._onStateChanged out
There is currently no simple way to inject into AppIcon's state change,
so an extension that wants to do this has to destroy/remove/update all
icons in the Shell (i.e. in the Dash, AllView, FrequentView) on enable()
and disable() after updating AppIcon.prototype._onStateChange, or the
extension must require a restart of the Shell.

To solve this issue, we rename _onStateChanged to _updateRunningStyle,
and connect the notify::state signal with an anonymous function that
calls _updateRunningStyle.
This extra function call should allow extensions to just extend the
updateRunningStyle function in the prototype.

https://bugzilla.gnome.org/show_bug.cgi?id=739497
2014-11-06 21:31:47 +01:00
f414f616c4 dateMenu: Fix typo in _isToday()
getDay() is the day of week, what we want there is getDate().

https://bugzilla.gnome.org/show_bug.cgi?id=738725
2014-11-03 15:05:59 +01:00
e21e90c5e6 networkAgent: Support NM versions without :capabilities
Commit 926de53c0c bumped the requirement for NetworkManager,
which is problematic on a stable branch; optionally fall back to
the previous code.

https://bugzilla.gnome.org/show_bug.cgi?id=738485
2014-10-31 12:41:23 +00:00
1e7b2ef51f Bump version to 3.14.1.5
Update NEWS
2014-10-30 11:22:27 +00:00
c291de7479 Calendar: Inline _ellipsizeEventTime into caller
This patch inlines the function _ellipsizeEventTime into its only caller
_addEvent. This also removes the need for the global const
EventEllipses and is thus removed by this commit as well.

https://bugzilla.gnome.org/show_bug.cgi?id=727302
2014-10-27 19:33:25 -05:00
aee1a18270 Calendar: sort multi-day events by ending day/time
With commit dc6a60dde, the calendar displays the ending day and time of
a continuing multi-day event on its ending day. This results in the list
not appearing to be sorted. This patch sorts the list according to the
displayed day/time.

With the two appointments
Thursday 0800-1000 Foo, and Wednesday 0900-Friday 1200 Bar and today
being Monday, the rest of the week list currently displays:
F ...1200 Bar
T    0800 Foo
With this patch, the displaying order is switched because Friday comes
after Thursday.

https://bugzilla.gnome.org/show_bug.cgi?id=727302
2014-10-27 19:33:25 -05:00
6c67f26e7d Calendar: Show multi-day event continuation
Currently, multi-day events are shown as individual appointments on each
day.  This patch ellipsizes multi-day events to indicate continuation on
the prior or following day (or other time-period.)

The time label spot is now replaced by a box layout that contains the
prefix ellipsis label, the time label and the postfix ellipsis label.
In order to keep the alignment, ellipses are merely invisible (zero
opacity) when hidden.

The ellipses are styled using the events-day-time-ellipses class which,
by default, take the color of the event text.

When RTL is used, the box contents are adjusted accordingly (clutter
does that for us).

An event spanning three days now displays "...All Day..." in the
calendar on the second day.

https://bugzilla.gnome.org/show_bug.cgi?id=727302
2014-10-27 19:33:25 -05:00
deb651acbf BackgroundCache: plug an Animation object leak
We need to return early in case the animation file is the same,
otherwise we'll create a new Animation object and leak the previous
one.

https://bugzilla.gnome.org/show_bug.cgi?id=739252
2014-10-27 18:28:39 +01:00
d2011f6d7f messageTray: Summarize notifications when messages queue up
It is really annoying for the user to acknowledge multiple notifications
when they queue up. So, to prevent a notification flood that has to be
handled by the user one-by-one, a summarized-notification feature is
added which leaves a single summarized-notification for the user,
replacing multiple notifications if the number exceeds 1, which they may
or may not acknowledge. When this summarized-notification is acknowledged,
the message-tray is opened where they can view the notifications that were
summarized. This helps the user concentrate on his primary task
simultaneously informing them about the new notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=702460
2014-10-27 18:22:36 +01:00
416adec904 Fix handling of SystemBackground
Since the background rework, SystemBackground is no longer a transparent
actor that you have to stack on top of a solid background, it is an
opaque actor. Fix the color of the background actor, and remove places
where we were setting the background color underneath the system background
and expecting blending - in particular, we can always set no_clear_hint
on the stage.

https://bugzilla.gnome.org/show_bug.cgi?id=738652
2014-10-16 17:17:33 -04:00
44 changed files with 542 additions and 2421 deletions

1
.gitignore vendored
View File

@ -23,7 +23,6 @@ data/gnome-shell-wayland.desktop
data/gnome-shell-wayland.desktop.in data/gnome-shell-wayland.desktop.in
data/gnome-shell-extension-prefs.desktop data/gnome-shell-extension-prefs.desktop
data/gnome-shell-extension-prefs.desktop.in data/gnome-shell-extension-prefs.desktop.in
data/gnome-shell-theme.gresource
data/gschemas.compiled data/gschemas.compiled
data/perf-background.xml data/perf-background.xml
data/org.gnome.shell.gschema.xml data/org.gnome.shell.gschema.xml

27
NEWS
View File

@ -1,19 +1,22 @@
3.15.1 3.14.2
====== ======
* Use GResources for theme loading [Cosimo; #736936] * Do not hard-depend on latest NetworkManager [Florian; #738485]
* Reset the OSK to primary on monitor changes [Rui; #738536] * Fix check for isToday in calendar [Darcy; #738725]
* Use LC_TIME locale for format string translations [Florian; #738640] * Fix workspace changes from app picker [Yuki; #737534]
* Summarize queued up notifications [Devyani; #702460] * Misc. bug fixes [Yuki; #739497]
* Improve handling of multi-day events [Andreas; #727302]
* Support EXTERNAL scroll policy type [Florian; #739379]
* Misc. bugfixes [Owen, Rui; #738652, #739252]
Contributors: Contributors:
Andreas Brauchli, Cosimo Cecchi, Devyani Kota, Rui Matos, Florian Müllner, Darcy, Florian Müllner, Yuki
Jasper St. Pierre, Owen W. Taylor
Translations: 3.14.1.5
Bahodir Mansurov [uz@cyrillic] ========
* Fix handing of SystemBackground [Owen; #738652]
* Summarize queued up notifications [Devyani; #702460]
* Plug an animation object leak [Rui; #739252]
* Improve handling of multi-day events [Andreas; #727302]
Contributors:
Andreas Brauchli, Devyani Kota, Rui Matos, Owen W. Taylor
3.14.1 3.14.1
====== ======

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.15.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.14.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@ -76,7 +76,7 @@ AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.15.90 CLUTTER_MIN_VERSION=1.15.90
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.39.0 GJS_MIN_VERSION=1.39.0
MUTTER_MIN_VERSION=3.15.1 MUTTER_MIN_VERSION=3.14.2
GTK_MIN_VERSION=3.13.2 GTK_MIN_VERSION=3.13.2
GIO_MIN_VERSION=2.37.0 GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3

View File

@ -35,11 +35,44 @@ introspection_DATA = \
org.gnome.ShellSearchProvider.xml \ org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml org.gnome.ShellSearchProvider2.xml
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/theme --generate-dependencies $(srcdir)/gnome-shell-theme.gresource.xml) themedir = $(pkgdatadir)/theme
gnome-shell-theme.gresource: gnome-shell-theme.gresource.xml $(resource_files) dist_theme_DATA = \
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/theme $< theme/calendar-arrow-left.svg \
resourcedir = $(pkgdatadir) theme/calendar-arrow-right.svg \
resource_DATA = gnome-shell-theme.gresource theme/calendar-today.svg \
theme/checkbox-focused.svg \
theme/checkbox-off-focused.svg \
theme/checkbox-off.svg \
theme/checkbox.svg \
theme/close-window.svg \
theme/close.svg \
theme/corner-ripple-ltr.png \
theme/corner-ripple-rtl.png \
theme/dash-placeholder.svg \
theme/filter-selected-ltr.svg \
theme/filter-selected-rtl.svg \
theme/gnome-shell.css \
theme/logged-in-indicator.svg \
theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \
theme/page-indicator-active.svg \
theme/page-indicator-inactive.svg \
theme/page-indicator-checked.svg \
theme/page-indicator-hover.svg \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \
theme/panel-button-highlight-wide.svg \
theme/process-working.svg \
theme/running-indicator.svg \
theme/source-button-border.svg \
theme/summary-counter.svg \
theme/toggle-off-us.svg \
theme/toggle-off-intl.svg \
theme/toggle-on-us.svg \
theme/toggle-on-intl.svg \
theme/ws-switch-arrow-up.png \
theme/ws-switch-arrow-down.png
backgrounddir = $(pkgdatadir) backgrounddir = $(pkgdatadir)
background_DATA = perf-background.xml background_DATA = perf-background.xml
@ -83,9 +116,7 @@ EXTRA_DIST = \
perf-background.xml.in \ perf-background.xml.in \
org.gnome.Shell.PortalHelper.desktop.in \ org.gnome.Shell.PortalHelper.desktop.in \
org.gnome.Shell.PortalHelper.service.in \ org.gnome.Shell.PortalHelper.service.in \
org.gnome.shell.gschema.xml.in.in \ org.gnome.shell.gschema.xml.in.in
gnome-shell-theme.gresource.xml \
$(resource_files)
CLEANFILES += \ CLEANFILES += \
gnome-shell.desktop.in \ gnome-shell.desktop.in \
@ -97,5 +128,4 @@ CLEANFILES += \
perf-background.xml \ perf-background.xml \
gschemas.compiled \ gschemas.compiled \
org.gnome.shell.gschema.valid \ org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in \ org.gnome.shell.gschema.xml.in
gnome-shell-theme.gresource

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/theme">
<file>calendar-arrow-left.svg</file>
<file>calendar-arrow-right.svg</file>
<file>calendar-today.svg</file>
<file>checkbox-focused.svg</file>
<file>checkbox-off-focused.svg</file>
<file>checkbox-off.svg</file>
<file>checkbox.svg</file>
<file>close-window.svg</file>
<file>close.svg</file>
<file>corner-ripple-ltr.png</file>
<file>corner-ripple-rtl.png</file>
<file>dash-placeholder.svg</file>
<file>filter-selected-ltr.svg</file>
<file>filter-selected-rtl.svg</file>
<file>gnome-shell.css</file>
<file>logged-in-indicator.svg</file>
<file>message-tray-background.png</file>
<file>more-results.svg</file>
<file>noise-texture.png</file>
<file>page-indicator-active.svg</file>
<file>page-indicator-inactive.svg</file>
<file>page-indicator-checked.svg</file>
<file>page-indicator-hover.svg</file>
<file>panel-button-border.svg</file>
<file>panel-button-highlight-narrow.svg</file>
<file>panel-button-highlight-wide.svg</file>
<file>process-working.svg</file>
<file>running-indicator.svg</file>
<file>source-button-border.svg</file>
<file>summary-counter.svg</file>
<file>toggle-off-us.svg</file>
<file>toggle-off-intl.svg</file>
<file>toggle-on-us.svg</file>
<file>toggle-on-intl.svg</file>
<file>ws-switch-arrow-up.png</file>
<file>ws-switch-arrow-down.png</file>
</gresource>
</gresources>

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
@ -127,7 +126,7 @@ const AuthPrompt = new Lang.Class({
this._initButtons(); this._initButtons();
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); let spinnerIcon = global.datadir + '/theme/process-working.svg';
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE); this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0; this._spinner.actor.opacity = 0;
this._spinner.actor.show(); this._spinner.actor.show();

View File

@ -537,24 +537,24 @@ const LoginDialog = new Lang.Class({
} }
}, },
_updateLogoTexture: function(cache, file) { _updateLogoTexture: function(cache, uri) {
if (this._logoFile && !this._logoFile.equal(file)) if (this._logoFileUri != uri)
return; return;
this._logoBin.destroy_all_children(); this._logoBin.destroy_all_children();
if (this._logoFile) { if (this._logoFileUri) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile, this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
-1, _LOGO_ICON_HEIGHT, -1, _LOGO_ICON_HEIGHT,
scaleFactor)); scaleFactor));
} }
}, },
_updateLogo: function() { _updateLogo: function() {
let path = this._settings.get_string(GdmUtil.LOGO_KEY); let path = this._settings.get_string(GdmUtil.LOGO_KEY);
this._logoFile = path ? Gio.file_new_for_path(path) : null; this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null;
this._updateLogoTexture(this._textureCache, this._logoFile); this._updateLogoTexture(this._textureCache, this._logoFileUri);
}, },
_onPrompted: function() { _onPrompted: function() {

View File

@ -35,7 +35,7 @@ function releaseKeyboard() {
} }
function holdKeyboard() { function holdKeyboard() {
global.display.freeze_keyboard(global.get_current_time()); global.freeze_keyboard(global.get_current_time());
} }
const KeyboardManager = new Lang.Class({ const KeyboardManager = new Lang.Class({

View File

@ -12,7 +12,7 @@ const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const Animation = new Lang.Class({ const Animation = new Lang.Class({
Name: 'Animation', Name: 'Animation',
_init: function(file, width, height, speed) { _init: function(filename, width, height, speed) {
this.actor = new St.Bin(); this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._speed = speed; this._speed = speed;
@ -23,7 +23,7 @@ const Animation = new Lang.Class({
this._frame = 0; this._frame = 0;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor, this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, scaleFactor,
Lang.bind(this, this._animationsLoaded)); Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations); this.actor.set_child(this._animations);
}, },
@ -82,7 +82,7 @@ const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon', Name: 'AnimatedIcon',
Extends: Animation, Extends: Animation,
_init: function(file, size) { _init: function(filename, size) {
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
} }
}); });

View File

@ -379,7 +379,9 @@ const AllView = new Lang.Class({
this.actor.add_actor(this._scrollView); this.actor.add_actor(this._scrollView);
this._scrollView.set_policy(Gtk.PolicyType.NEVER, this._scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.EXTERNAL); Gtk.PolicyType.AUTOMATIC);
// we are only using ScrollView for the fade effect, hide scrollbars
this._scrollView.vscroll.hide();
this._adjustment = this._scrollView.vscroll.adjustment; this._adjustment = this._scrollView.vscroll.adjustment;
this._pageIndicators = new PageIndicators(); this._pageIndicators = new PageIndicators();
@ -1562,10 +1564,11 @@ const AppIcon = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._menuTimeoutId = 0; this._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', this._stateChangedId = this.app.connect('notify::state', Lang.bind(this,
Lang.bind(this, function () {
this._onStateChanged)); this._updateRunningStyle();
this._onStateChanged(); }));
this._updateRunningStyle();
}, },
_onDestroy: function() { _onDestroy: function() {
@ -1586,7 +1589,7 @@ const AppIcon = new Lang.Class({
} }
}, },
_onStateChanged: function() { _updateRunningStyle: function() {
if (this.app.state != Shell.AppState.STOPPED) if (this.app.state != Shell.AppState.STOPPED)
this.actor.add_style_class_name('running'); this.actor.add_style_class_name('running');
else else

View File

@ -127,16 +127,6 @@ const ANIMATION_MIN_WAKEUP_INTERVAL = 1.0;
let _backgroundCache = null; let _backgroundCache = null;
function _fileEqual0(file1, file2) {
if (file1 == file2)
return true;
if (!file1 || !file2)
return false;
return file1.equal(file2);
}
const BackgroundCache = new Lang.Class({ const BackgroundCache = new Lang.Class({
Name: 'BackgroundCache', Name: 'BackgroundCache',
@ -146,25 +136,25 @@ const BackgroundCache = new Lang.Class({
this._backgroundSources = {}; this._backgroundSources = {};
}, },
monitorFile: function(file) { monitorFile: function(filename) {
let key = file.hash(); if (this._fileMonitors[filename])
if (this._fileMonitors[key])
return; return;
let file = Gio.File.new_for_path(filename);
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null); let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', monitor.connect('changed',
Lang.bind(this, function() { Lang.bind(this, function() {
this.emit('file-changed', file); this.emit('file-changed', filename);
})); }));
this._fileMonitors[key] = monitor; this._fileMonitors[filename] = monitor;
}, },
getAnimation: function(params) { getAnimation: function(params) {
params = Params.parse(params, { file: null, params = Params.parse(params, { filename: null,
onLoaded: null }); onLoaded: null });
if (_fileEqual0(this._animationFile, params.file)) { if (this._animationFilename == params.filename) {
if (params.onLoaded) { if (params.onLoaded) {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() { let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
params.onLoaded(this._animation); params.onLoaded(this._animation);
@ -175,10 +165,10 @@ const BackgroundCache = new Lang.Class({
return; return;
} }
let animation = new Animation({ file: params.file }); let animation = new Animation({ filename: params.filename });
animation.load(Lang.bind(this, function() { animation.load(Lang.bind(this, function() {
this._animationFile = params.file; this._animationFilename = params.filename;
this._animation = animation; this._animation = animation;
if (params.onLoaded) { if (params.onLoaded) {
@ -231,14 +221,14 @@ const Background = new Lang.Class({
params = Params.parse(params, { monitorIndex: 0, params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager, layoutManager: Main.layoutManager,
settings: null, settings: null,
file: null, filename: null,
style: null }); style: null });
this.background = new Meta.Background({ meta_screen: global.screen }); this.background = new Meta.Background({ meta_screen: global.screen });
this.background._delegate = this; this.background._delegate = this;
this._settings = params.settings; this._settings = params.settings;
this._file = params.file; this._filename = params.filename;
this._style = params.style; this._style = params.style;
this._monitorIndex = params.monitorIndex; this._monitorIndex = params.monitorIndex;
this._layoutManager = params.layoutManager; this._layoutManager = params.layoutManager;
@ -305,21 +295,20 @@ const Background = new Lang.Class({
this.background.set_gradient(shadingType, color, secondColor); this.background.set_gradient(shadingType, color, secondColor);
}, },
_watchFile: function(file) { _watchFile: function(filename) {
let key = file.hash(); if (this._fileWatches[filename])
if (this._fileWatches[key])
return; return;
this._cache.monitorFile(file); this._cache.monitorFile(filename);
let signalId = this._cache.connect('file-changed', let signalId = this._cache.connect('file-changed',
Lang.bind(this, function(cache, changedFile) { Lang.bind(this, function(cache, changedFile) {
if (changedFile.equal(file)) { if (changedFile == filename) {
let imageCache = Meta.BackgroundImageCache.get_default(); let imageCache = Meta.BackgroundImageCache.get_default();
imageCache.purge(changedFile); imageCache.purge(changedFile);
this.emit('changed'); this.emit('changed');
} }
})); }));
this._fileWatches[key] = signalId; this._fileWatches[filename] = signalId;
}, },
_removeAnimationTimeout: function() { _removeAnimationTimeout: function() {
@ -342,9 +331,9 @@ const Background = new Lang.Class({
this._animation.transitionProgress, this._animation.transitionProgress,
this._style); this._style);
} else if (files.length > 0) { } else if (files.length > 0) {
this.background.set_file(files[0], this._style); this.background.set_filename(files[0], this._style);
} else { } else {
this.background.set_file(null, this._style); this.background.set_filename(null, this._style);
} }
this._queueUpdateAnimation(); this._queueUpdateAnimation();
}); });
@ -401,28 +390,28 @@ const Background = new Lang.Class({
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation'); GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
}, },
_loadAnimation: function(file) { _loadAnimation: function(filename) {
this._cache.getAnimation({ file: file, this._cache.getAnimation({ filename: filename,
onLoaded: Lang.bind(this, function(animation) { onLoaded: Lang.bind(this, function(animation) {
this._animation = animation; this._animation = animation;
if (!this._animation || this._cancellable.is_cancelled()) { if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded(); this._setLoaded();
return; return;
} }
this._updateAnimation(); this._updateAnimation();
this._watchFile(file); this._watchFile(filename);
}) })
}); });
}, },
_loadImage: function(file) { _loadImage: function(filename) {
this.background.set_file(file, this._style); this.background.set_filename(filename, this._style);
this._watchFile(file); this._watchFile(filename);
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file); let image = cache.load(filename);
if (image.is_loaded()) if (image.is_loaded())
this._setLoaded(); this._setLoaded();
else { else {
@ -434,11 +423,11 @@ const Background = new Lang.Class({
} }
}, },
_loadFile: function(file) { _loadFile: function(filename) {
if (file.get_basename().endsWith('.xml')) if (filename.endsWith('.xml'))
this._loadAnimation(file); this._loadAnimation(filename);
else else
this._loadImage(file); this._loadImage(filename);
}, },
_load: function () { _load: function () {
@ -446,12 +435,12 @@ const Background = new Lang.Class({
this._loadPattern(); this._loadPattern();
if (!this._file) { if (!this._filename) {
this._setLoaded(); this._setLoaded();
return; return;
} }
this._loadFile(this._file); this._loadFile(this._filename);
}, },
}); });
Signals.addSignalMethods(Background.prototype); Signals.addSignalMethods(Background.prototype);
@ -462,12 +451,12 @@ const SystemBackground = new Lang.Class({
Name: 'SystemBackground', Name: 'SystemBackground',
_init: function() { _init: function() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png'); let filename = global.datadir + '/theme/noise-texture.png';
if (_systemBackground == null) { if (_systemBackground == null) {
_systemBackground = new Meta.Background({ meta_screen: global.screen }); _systemBackground = new Meta.Background({ meta_screen: global.screen });
_systemBackground.set_color(DEFAULT_BACKGROUND_COLOR); _systemBackground.set_color(DEFAULT_BACKGROUND_COLOR);
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER); _systemBackground.set_filename(filename, GDesktopEnums.BackgroundStyle.WALLPAPER);
} }
this.actor = new Meta.BackgroundActor({ meta_screen: global.screen, this.actor = new Meta.BackgroundActor({ meta_screen: global.screen,
@ -475,7 +464,7 @@ const SystemBackground = new Lang.Class({
background: _systemBackground }); background: _systemBackground });
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file); let image = cache.load(filename);
if (image.is_loaded()) { if (image.is_loaded()) {
image = null; image = null;
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() { let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
@ -524,17 +513,20 @@ const BackgroundSource = new Lang.Class({
}, },
getBackground: function(monitorIndex) { getBackground: function(monitorIndex) {
let file = null; let filename = null;
let style; let style;
if (this._overrideImage != null) { if (this._overrideImage != null) {
file = Gio.File.new_for_path(this._overrideImage); filename = this._overrideImage;
style = GDesktopEnums.BackgroundStyle.ZOOM; // Hardcode style = GDesktopEnums.BackgroundStyle.ZOOM; // Hardcode
} else { } else {
style = this._settings.get_enum(BACKGROUND_STYLE_KEY); style = this._settings.get_enum(BACKGROUND_STYLE_KEY);
if (style != GDesktopEnums.BackgroundStyle.NONE) { if (style != GDesktopEnums.BackgroundStyle.NONE) {
let uri = this._settings.get_string(PICTURE_URI_KEY); let uri = this._settings.get_string(PICTURE_URI_KEY);
file = Gio.File.new_for_commandline_arg(uri); if (GLib.uri_parse_scheme(uri) != null)
filename = Gio.File.new_for_uri(uri).get_path();
else
filename = uri;
} }
} }
@ -542,7 +534,7 @@ const BackgroundSource = new Lang.Class({
// they can have variants that depend on the aspect ratio and // they can have variants that depend on the aspect ratio and
// size of the monitor; for other backgrounds we can use the // size of the monitor; for other backgrounds we can use the
// same background object for all monitors. // same background object for all monitors.
if (file == null || !file.get_basename().endsWith('.xml')) if (filename == null || !filename.endsWith('.xml'))
monitorIndex = 0; monitorIndex = 0;
if (!(monitorIndex in this._backgrounds)) { if (!(monitorIndex in this._backgrounds)) {
@ -550,7 +542,7 @@ const BackgroundSource = new Lang.Class({
monitorIndex: monitorIndex, monitorIndex: monitorIndex,
layoutManager: this._layoutManager, layoutManager: this._layoutManager,
settings: this._settings, settings: this._settings,
file: file, filename: filename,
style: style style: style
}); });
@ -583,9 +575,9 @@ const Animation = new Lang.Class({
Name: 'Animation', Name: 'Animation',
_init: function(params) { _init: function(params) {
params = Params.parse(params, { file: null }); params = Params.parse(params, { filename: null });
this.file = params.file; this.filename = params.filename;
this.keyFrameFiles = []; this.keyFrameFiles = [];
this.transitionProgress = 0.0; this.transitionProgress = 0.0;
this.transitionDuration = 0.0; this.transitionDuration = 0.0;
@ -593,7 +585,9 @@ const Animation = new Lang.Class({
}, },
load: function(callback) { load: function(callback) {
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() }); let file = Gio.File.new_for_path(this.filename);
this._show = new GnomeDesktop.BGSlideShow({ filename: this.filename });
this._show.load_async(null, this._show.load_async(null,
Lang.bind(this, Lang.bind(this,
@ -613,16 +607,16 @@ const Animation = new Lang.Class({
if (this._show.get_num_slides() < 1) if (this._show.get_num_slides() < 1)
return; return;
let [progress, duration, isFixed, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height); let [progress, duration, isFixed, file1, file2] = this._show.get_current_slide(monitor.width, monitor.height);
this.transitionDuration = duration; this.transitionDuration = duration;
this.transitionProgress = progress; this.transitionProgress = progress;
if (filename1) if (file1)
this.keyFrameFiles.push(Gio.File.new_for_path(filename1)); this.keyFrameFiles.push(file1);
if (filename2) if (file2)
this.keyFrameFiles.push(Gio.File.new_for_path(filename2)); this.keyFrameFiles.push(file2);
}, },
}); });
Signals.addSignalMethods(Animation.prototype); Signals.addSignalMethods(Animation.prototype);

View File

@ -17,7 +17,6 @@ const ELLIPSIS_CHAR = '\u2026';
// alias to prevent xgettext from picking up strings translated in GTK+ // alias to prevent xgettext from picking up strings translated in GTK+
const gtk30_ = Gettext_gtk30.gettext; const gtk30_ = Gettext_gtk30.gettext;
const NC_ = function(context, str) { return str; };
// in org.gnome.desktop.interface // in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format'; const CLOCK_FORMAT_KEY = 'clock-format';
@ -819,17 +818,14 @@ const EventsList = new Lang.Class({
let dayBegin = _getBeginningOfDay(day); let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day); let dayEnd = _getEndOfDay(day);
let dayFormat; let dayString;
let now = new Date(); let now = new Date();
if (_sameYear(day, now)) if (_sameYear(day, now))
/* Translators: Shown on calendar heading when selected day occurs on current year */ /* Translators: Shown on calendar heading when selected day occurs on current year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading", dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d"));
"%A, %B %d"));
else else
/* Translators: Shown on calendar heading when selected day occurs on different year */ /* Translators: Shown on calendar heading when selected day occurs on different year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading", dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d, %Y"));
"%A, %B %d, %Y"));
let dayString = day.toLocaleFormat(dayFormat);
this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true); this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true);
}, },

View File

@ -604,9 +604,15 @@ const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent', Name: 'NetworkAgent',
_init: function() { _init: function() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent', try {
capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
}); capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS
});
} catch(e) {
// Support older versions without NetworkAgent:capabilities
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent'
});
}
this._dialogs = { }; this._dialogs = { };
this._vpnRequests = { }; this._vpnRequests = { };

View File

@ -36,8 +36,6 @@ const NotificationDirection = {
RECEIVED: 'chat-received' RECEIVED: 'chat-received'
}; };
const N_ = function(s) { return s; };
function makeMessageFromTpMessage(tpMessage, direction) { function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text(); let [text, flags] = tpMessage.to_text();
@ -952,70 +950,70 @@ const ChatNotification = new Lang.Class({
// Show only the time if date is on today // Show only the time if date is on today
if(daysAgo < 1){ if(daysAgo < 1){
/* Translators: Time in 24h format */ /* Translators: Time in 24h format */
format = N_("%H\u2236%M"); format = _("%H\u2236%M");
} }
// Show the word "Yesterday" and time if date is on yesterday // Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){ else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a /* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */ time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("Yesterday, %H\u2236%M"); format = _("Yesterday, %H\u2236%M");
} }
// Show a week day and time if date is in the last week // Show a week day and time if date is in the last week
else if (daysAgo < 7) { else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time /* Translators: this is the week day name followed by a time
string in 24h format. i.e. "Monday, 14:30" */ string in 24h format. i.e. "Monday, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%A, %H\u2236%M"); format = _("%A, %H\u2236%M");
} else if (date.getYear() == now.getYear()) { } else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number /* Translators: this is the month name and day number
followed by a time string in 24h format. followed by a time string in 24h format.
i.e. "May 25, 14:30" */ i.e. "May 25, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%B %d, %H\u2236%M"); format = _("%B %d, %H\u2236%M");
} else { } else {
/* Translators: this is the month name, day number, year /* Translators: this is the month name, day number, year
number followed by a time string in 24h format. number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */ i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%B %d %Y, %H\u2236%M"); format = _("%B %d %Y, %H\u2236%M");
} }
} else { } else {
// Show only the time if date is on today // Show only the time if date is on today
if(daysAgo < 1){ if(daysAgo < 1){
/* Translators: Time in 24h format */ /* Translators: Time in 24h format */
format = N_("%l\u2236%M %p"); format = _("%l\u2236%M %p");
} }
// Show the word "Yesterday" and time if date is on yesterday // Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){ else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a /* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */ time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("Yesterday, %l\u2236%M %p"); format = _("Yesterday, %l\u2236%M %p");
} }
// Show a week day and time if date is in the last week // Show a week day and time if date is in the last week
else if (daysAgo < 7) { else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time /* Translators: this is the week day name followed by a time
string in 12h format. i.e. "Monday, 2:30 pm" */ string in 12h format. i.e. "Monday, 2:30 pm" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%A, %l\u2236%M %p"); format = _("%A, %l\u2236%M %p");
} else if (date.getYear() == now.getYear()) { } else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number /* Translators: this is the month name and day number
followed by a time string in 12h format. followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */ i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%B %d, %l\u2236%M %p"); format = _("%B %d, %l\u2236%M %p");
} else { } else {
/* Translators: this is the month name, day number, year /* Translators: this is the month name, day number, year
number followed by a time string in 12h format. number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/ i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format // xgettext:no-c-format
format = N_("%B %d %Y, %l\u2236%M %p"); format = _("%B %d %Y, %l\u2236%M %p");
} }
} }
return date.toLocaleFormat(Shell.util_translate_time_string(format)); return date.toLocaleFormat(format);
}, },
appendTimestamp: function() { appendTimestamp: function() {
@ -1266,8 +1264,9 @@ const SubscriptionRequestNotification = new Lang.Class({
let file = contact.get_avatar_file(); let file = contact.get_avatar_file();
if (file) { if (file) {
let uri = file.get_uri();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
iconBox.child = textureCache.load_file_async(file, iconBox._size, iconBox._size, scaleFactor); iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size, scaleFactor);
} }
else { else {
iconBox.child = new St.Icon({ icon_name: 'avatar-default', iconBox.child = new St.Icon({ icon_name: 'avatar-default',

View File

@ -129,7 +129,7 @@ const DateMenuButton = new Lang.Class({
/* Translators: This is the date format to use when the calendar popup is /* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
*/ */
let dateFormat = Shell.util_translate_time_string ("%A %B %e, %Y"); let dateFormat = _("%A %B %e, %Y");
this._date.set_label(now.toLocaleFormat(dateFormat)); this._date.set_label(now.toLocaleFormat(dateFormat));
} }
})); }));
@ -147,7 +147,7 @@ const DateMenuButton = new Lang.Class({
let now = new Date(); let now = new Date();
return now.getYear() == date.getYear() && return now.getYear() == date.getYear() &&
now.getMonth() == date.getMonth() && now.getMonth() == date.getMonth() &&
now.getDay() == date.getDay(); now.getDate() == date.getDate();
}, },
_appInstalledChanged: function() { _appInstalledChanged: function() {

View File

@ -74,7 +74,7 @@ function disableExtension(uuid) {
if (extension.stylesheet) { if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet); theme.unload_stylesheet(extension.stylesheet.get_path());
} }
try { try {
@ -118,7 +118,7 @@ function enableExtension(uuid) {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
if (stylesheetFile.query_exists(null)) { if (stylesheetFile.query_exists(null)) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.load_stylesheet(stylesheetFile); theme.load_stylesheet(stylesheetFile.get_path());
extension.stylesheet = stylesheetFile; extension.stylesheet = stylesheetFile;
break; break;
} }

View File

@ -422,7 +422,10 @@ const LayoutManager = new Lang.Class({
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y); this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1); this.panelBox.set_size(this.primaryMonitor.width, -1);
this.keyboardIndex = this.primaryIndex; if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex;
else
this._updateKeyboardBox();
this.trayBox.set_position(this.bottomMonitor.x, this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height); this.bottomMonitor.y + this.bottomMonitor.height);

View File

@ -129,9 +129,6 @@ function _initializeUI() {
Shell.WindowTracker.get_default(); Shell.WindowTracker.get_default();
Shell.AppUsage.get_default(); Shell.AppUsage.get_default();
let resource = Gio.Resource.load(global.datadir + '/gnome-shell-theme.gresource');
resource._register();
_loadDefaultStylesheet(); _loadDefaultStylesheet();
// Setup the stage hierarchy early // Setup the stage hierarchy early
@ -225,26 +222,12 @@ function _initializeUI() {
}); });
} }
function _getDefaultStylesheet() {
let stylesheet;
stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + sessionMode.stylesheetName);
if (stylesheet.query_exists(null))
return stylesheet;
stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + sessionMode.stylesheetName);
if (stylesheet.query_exists(null))
return stylesheet;
return null;
}
function _loadDefaultStylesheet() { function _loadDefaultStylesheet() {
if (!sessionMode.isPrimary) if (!sessionMode.isPrimary)
return; return;
let stylesheet = _getDefaultStylesheet(); let stylesheet = global.datadir + '/theme/' + sessionMode.stylesheetName;
if (_defaultCssStylesheet && _defaultCssStylesheet.equal(stylesheet)) if (_defaultCssStylesheet == stylesheet)
return; return;
_defaultCssStylesheet = stylesheet; _defaultCssStylesheet = stylesheet;
@ -271,7 +254,7 @@ function getThemeStylesheet() {
* Set the theme CSS file that the shell will load * Set the theme CSS file that the shell will load
*/ */
function setThemeStylesheet(cssStylesheet) { function setThemeStylesheet(cssStylesheet) {
_cssStylesheet = Gio.File.new_for_path(cssStylesheet); _cssStylesheet = cssStylesheet;
} }
/** /**

View File

@ -194,7 +194,7 @@ const ModalDialog = new Lang.Class({
}, },
placeSpinner: function(layoutInfo) { placeSpinner: function(layoutInfo) {
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); let spinnerIcon = global.datadir + '/theme/process-working.svg';
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE); this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0; this._workSpinner.actor.opacity = 0;
this._workSpinner.actor.show(); this._workSpinner.actor.show();

View File

@ -273,7 +273,7 @@ const AppMenuButton = new Lang.Class({
_onStyleChanged: function(actor) { _onStyleChanged: function(actor) {
let node = actor.get_theme_node(); let node = actor.get_theme_node();
let [success, icon] = node.lookup_url('spinner-image', false); let [success, icon] = node.lookup_url('spinner-image', false);
if (!success || (this._spinnerIcon && this._spinnerIcon.equal(icon))) if (!success || this._spinnerIcon == icon)
return; return;
this._spinnerIcon = icon; this._spinnerIcon = icon;
this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE); this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);

View File

@ -85,8 +85,7 @@ const Clock = new Lang.Class({
let date = new Date(); let date = new Date();
/* Translators: This is a time format for a date in /* Translators: This is a time format for a date in
long format */ long format */
let dateFormat = Shell.util_translate_time_string("%A, %B %d"); this._date.text = date.toLocaleFormat(_("%A, %B %d"));
this._date.text = date.toLocaleFormat(dateFormat);
}, },
destroy: function() { destroy: function() {

View File

@ -876,8 +876,7 @@ const NMWirelessDialog = new Lang.Class({
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); this._noNetworksSpinner = new Animation.AnimatedIcon(global.datadir + '/theme/process-working.svg', 24, 24);
this._noNetworksSpinner = new Animation.AnimatedIcon(file, 24, 24);
this._noNetworksBox.add_actor(this._noNetworksSpinner.actor); this._noNetworksBox.add_actor(this._noNetworksSpinner.actor);
this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label', this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label',
text: _("No Networks") })); text: _("No Networks") }));

View File

@ -193,8 +193,10 @@ const ViewSelector = new Lang.Class({
// the windows to animate, but now we no longer want to // the windows to animate, but now we no longer want to
// show it given that we are now on the apps page or // show it given that we are now on the apps page or
// search page. // search page.
if (this._activePage != this._workspacesPage) if (this._activePage != this._workspacesPage) {
this._workspacesPage.opacity = 0; this._workspacesPage.opacity = 0;
this._workspacesPage.hide();
}
})); }));
Main.wm.addKeybinding('toggle-application-view', Main.wm.addKeybinding('toggle-application-view',

View File

@ -68,7 +68,6 @@ th
tr tr
ug ug
uk uk
uz@cyrillic
vi vi
zh_CN zh_CN
zh_HK zh_HK

File diff suppressed because it is too large Load Diff

View File

@ -1132,6 +1132,14 @@ shell_global_end_modal (ShellGlobal *global,
sync_input_region (global); sync_input_region (global);
} }
void
shell_global_freeze_keyboard (ShellGlobal *global,
guint32 timestamp)
{
if (global->stage_xwindow != None)
meta_display_freeze_keyboard (global->meta_display, global->stage_xwindow, timestamp);
}
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib. /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
* *
* Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering

View File

@ -45,6 +45,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
MetaModalOptions options); MetaModalOptions options);
void shell_global_end_modal (ShellGlobal *global, void shell_global_end_modal (ShellGlobal *global,
guint32 timestamp); guint32 timestamp);
void shell_global_freeze_keyboard (ShellGlobal *global,
guint32 timestamp);
void shell_global_set_stage_input_region (ShellGlobal *global, void shell_global_set_stage_input_region (ShellGlobal *global,
GSList *rectangles); GSList *rectangles);

View File

@ -12,7 +12,6 @@
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include <X11/extensions/XTest.h> #include <X11/extensions/XTest.h>
#include <locale.h>
#ifdef HAVE__NL_TIME_FIRST_WEEKDAY #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
#include <langinfo.h> #include <langinfo.h>
#endif #endif
@ -209,32 +208,6 @@ shell_util_get_week_start ()
return week_start; return week_start;
} }
/**
* shell_util_translate_time_string:
* @str: String to translate
*
* Translate @str according to the locale defined by LC_TIME; unlike
* dcgettext(), the translations is still taken from the LC_MESSAGES
* catalogue and not the LC_TIME one.
*
* Returns: the translated string
*/
const char *
shell_util_translate_time_string (const char *str)
{
const char *locale = g_getenv ("LC_TIME");
const char *res;
if (locale)
setlocale (LC_MESSAGES, locale);
res = gettext (str);
setlocale (LC_MESSAGES, "");
return res;
}
/** /**
* shell_write_string_to_stream: * shell_write_string_to_stream:
* @stream: a #GOutputStream * @stream: a #GOutputStream

View File

@ -21,7 +21,6 @@ int shell_util_get_week_start (void);
char *shell_util_format_date (const char *format, char *shell_util_format_date (const char *format,
gint64 time_ms); gint64 time_ms);
const char *shell_util_translate_time_string (const char *str);
gboolean shell_write_string_to_stream (GOutputStream *stream, gboolean shell_write_string_to_stream (GOutputStream *stream,
const char *str, const char *str,

View File

@ -27,7 +27,7 @@
struct _StBorderImage { struct _StBorderImage {
GObject parent; GObject parent;
GFile *file; char *filename;
int border_top; int border_top;
int border_right; int border_right;
int border_bottom; int border_bottom;
@ -48,7 +48,7 @@ st_border_image_finalize (GObject *object)
{ {
StBorderImage *image = ST_BORDER_IMAGE (object); StBorderImage *image = ST_BORDER_IMAGE (object);
g_object_unref (image->file); g_free (image->filename);
G_OBJECT_CLASS (st_border_image_parent_class)->finalize (object); G_OBJECT_CLASS (st_border_image_parent_class)->finalize (object);
} }
@ -67,18 +67,18 @@ st_border_image_init (StBorderImage *image)
} }
StBorderImage * StBorderImage *
st_border_image_new (GFile *file, st_border_image_new (const char *filename,
int border_top, int border_top,
int border_right, int border_right,
int border_bottom, int border_bottom,
int border_left, int border_left,
int scale_factor) int scale_factor)
{ {
StBorderImage *image; StBorderImage *image;
image = g_object_new (ST_TYPE_BORDER_IMAGE, NULL); image = g_object_new (ST_TYPE_BORDER_IMAGE, NULL);
image->file = g_object_ref (file); image->filename = g_strdup (filename);
image->border_top = border_top; image->border_top = border_top;
image->border_right = border_right; image->border_right = border_right;
image->border_bottom = border_bottom; image->border_bottom = border_bottom;
@ -88,18 +88,12 @@ st_border_image_new (GFile *file,
return image; return image;
} }
/** const char *
* st_border_image_get_file: st_border_image_get_filename (StBorderImage *image)
* @image: a #StBorder_Image
*
* Returns: (transfer none): the #GFile for the #StBorder_Image
*/
GFile *
st_border_image_get_file (StBorderImage *image)
{ {
g_return_val_if_fail (ST_IS_BORDER_IMAGE (image), NULL); g_return_val_if_fail (ST_IS_BORDER_IMAGE (image), NULL);
return image->file; return image->filename;
} }
void void
@ -141,5 +135,5 @@ st_border_image_equal (StBorderImage *image,
image->border_right == other->border_right && image->border_right == other->border_right &&
image->border_bottom == other->border_bottom && image->border_bottom == other->border_bottom &&
image->border_left == other->border_left && image->border_left == other->border_left &&
g_file_equal (image->file, other->file)); strcmp (image->filename, other->filename) == 0);
} }

View File

@ -22,7 +22,6 @@
#define __ST_BORDER_IMAGE_H__ #define __ST_BORDER_IMAGE_H__
#include <glib-object.h> #include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -40,14 +39,14 @@ typedef struct _StBorderImageClass StBorderImageClass;
GType st_border_image_get_type (void) G_GNUC_CONST; GType st_border_image_get_type (void) G_GNUC_CONST;
StBorderImage *st_border_image_new (GFile *file, StBorderImage *st_border_image_new (const char *filename,
int border_top, int border_top,
int border_right, int border_right,
int border_bottom, int border_bottom,
int border_left, int border_left,
int scale_factor); int scale_factor);
GFile *st_border_image_get_file (StBorderImage *image); const char *st_border_image_get_filename (StBorderImage *image);
void st_border_image_get_borders (StBorderImage *image, void st_border_image_get_borders (StBorderImage *image,
int *border_top, int *border_top,
int *border_right, int *border_right,

View File

@ -373,7 +373,6 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
case GTK_POLICY_AUTOMATIC: case GTK_POLICY_AUTOMATIC:
case GTK_POLICY_EXTERNAL:
/* Should theoretically use the min width of the hscrollbar, /* Should theoretically use the min width of the hscrollbar,
* but that's not cleanly defined at the moment */ * but that's not cleanly defined at the moment */
min_width = 0; min_width = 0;
@ -383,7 +382,6 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
switch (priv->vscrollbar_policy) switch (priv->vscrollbar_policy)
{ {
case GTK_POLICY_NEVER: case GTK_POLICY_NEVER:
case GTK_POLICY_EXTERNAL:
account_for_vscrollbar = FALSE; account_for_vscrollbar = FALSE;
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
@ -445,7 +443,6 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
switch (priv->vscrollbar_policy) switch (priv->vscrollbar_policy)
{ {
case GTK_POLICY_NEVER: case GTK_POLICY_NEVER:
case GTK_POLICY_EXTERNAL:
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
case GTK_POLICY_AUTOMATIC: case GTK_POLICY_AUTOMATIC:
@ -457,7 +454,6 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
switch (priv->hscrollbar_policy) switch (priv->hscrollbar_policy)
{ {
case GTK_POLICY_NEVER: case GTK_POLICY_NEVER:
case GTK_POLICY_EXTERNAL:
account_for_hscrollbar = FALSE; account_for_hscrollbar = FALSE;
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
@ -484,7 +480,6 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
case GTK_POLICY_AUTOMATIC: case GTK_POLICY_AUTOMATIC:
case GTK_POLICY_EXTERNAL:
/* Should theoretically use the min height of the vscrollbar, /* Should theoretically use the min height of the vscrollbar,
* but that's not cleanly defined at the moment */ * but that's not cleanly defined at the moment */
min_height = 0; min_height = 0;
@ -572,7 +567,7 @@ st_scroll_view_allocate (ClutterActor *actor,
} }
else else
{ {
hscrollbar_visible = priv->hscrollbar_policy == GTK_POLICY_ALWAYS; hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
/* try without a vertical scrollbar */ /* try without a vertical scrollbar */
clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL); clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL);
@ -581,20 +576,18 @@ st_scroll_view_allocate (ClutterActor *actor,
} }
else else
{ {
vscrollbar_visible = priv->vscrollbar_policy == GTK_POLICY_ALWAYS; vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC) if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width); hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width);
else else
hscrollbar_visible = priv->hscrollbar_policy == GTK_POLICY_ALWAYS; hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
} }
} }
else else
{ {
hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER && hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
priv->hscrollbar_policy != GTK_POLICY_EXTERNAL; vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER &&
priv->vscrollbar_policy != GTK_POLICY_EXTERNAL;
} }
/* Whether or not we show the scrollbars, if the scrollbars are visible /* Whether or not we show the scrollbars, if the scrollbars are visible
@ -636,19 +629,15 @@ st_scroll_view_allocate (ClutterActor *actor,
clutter_actor_allocate (priv->hscroll, &child_box, flags); clutter_actor_allocate (priv->hscroll, &child_box, flags);
/* In case the scrollbar policy is NEVER or EXTERNAL or scrollbars /* In case the scrollbar policy is NEVER or scrollbars should be
* should be overlayed, we don't trim the content box allocation by * overlayed, we don't trim the content box allocation by the
* the scrollbar size. * scrollbar size.
* Fold this into the scrollbar sizes to simplify the rest of the * Fold this into the scrollbar sizes to simplify the rest of the
* computations. * computations.
*/ */
if (priv->hscrollbar_policy == GTK_POLICY_NEVER || if (priv->hscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
priv->hscrollbar_policy == GTK_POLICY_EXTERNAL ||
priv->overlay_scrollbars)
sb_height = 0; sb_height = 0;
if (priv->vscrollbar_policy == GTK_POLICY_NEVER || if (priv->vscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
priv->vscrollbar_policy == GTK_POLICY_EXTERNAL ||
priv->overlay_scrollbars)
sb_width = 0; sb_width = 0;
/* Child */ /* Child */

View File

@ -28,8 +28,8 @@
#include <glib.h> #include <glib.h>
#define CACHE_PREFIX_ICON "icon:" #define CACHE_PREFIX_ICON "icon:"
#define CACHE_PREFIX_FILE "file:" #define CACHE_PREFIX_URI "uri:"
#define CACHE_PREFIX_FILE_FOR_CAIRO "file-for-cairo:" #define CACHE_PREFIX_URI_FOR_CAIRO "uri-for-cairo:"
struct _StTextureCachePrivate struct _StTextureCachePrivate
{ {
@ -101,7 +101,7 @@ st_texture_cache_class_init (StTextureCacheClass *klass)
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
0, /* no default handler slot */ 0, /* no default handler slot */
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_FILE); G_TYPE_NONE, 1, G_TYPE_STRING);
} }
/* Evicts all cached textures for named icons */ /* Evicts all cached textures for named icons */
@ -147,7 +147,7 @@ st_texture_cache_init (StTextureCache *self)
g_free, cogl_object_unref); g_free, cogl_object_unref);
self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal, self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL); g_free, NULL);
self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, self->priv->file_monitors = g_hash_table_new_full (g_str_hash, g_str_equal,
g_object_unref, g_object_unref); g_object_unref, g_object_unref);
} }
@ -268,7 +268,7 @@ typedef struct {
GtkIconInfo *icon_info; GtkIconInfo *icon_info;
StIconColors *colors; StIconColors *colors;
GFile *file; char *uri;
} AsyncTextureLoadData; } AsyncTextureLoadData;
static void static void
@ -282,8 +282,8 @@ texture_load_data_free (gpointer p)
if (data->colors) if (data->colors)
st_icon_colors_unref (data->colors); st_icon_colors_unref (data->colors);
} }
else if (data->file) else if (data->uri)
g_object_unref (data->file); g_free (data->uri);
if (data->key) if (data->key)
g_free (data->key); g_free (data->key);
@ -405,17 +405,83 @@ out:
return rotated_pixbuf; return rotated_pixbuf;
} }
static GdkPixbuf*
decode_image (const char *val)
{
int i;
GError *error = NULL;
GdkPixbuf *res = NULL;
struct {
const char *prefix;
const char *mime_type;
} formats[] = {
{ "data:image/x-icon;base64,", "image/x-icon" },
{ "data:image/png;base64,", "image/png" }
};
g_return_val_if_fail (val, NULL);
for (i = 0; i < G_N_ELEMENTS (formats); i++)
{
if (g_str_has_prefix (val, formats[i].prefix))
{
gsize len;
guchar *data = NULL;
char *unescaped;
unescaped = g_uri_unescape_string (val + strlen (formats[i].prefix), NULL);
if (unescaped)
{
data = g_base64_decode (unescaped, &len);
g_free (unescaped);
}
if (data)
{
GdkPixbufLoader *loader;
loader = gdk_pixbuf_loader_new_with_mime_type (formats[i].mime_type, &error);
if (loader &&
gdk_pixbuf_loader_write (loader, data, len, &error) &&
gdk_pixbuf_loader_close (loader, &error))
{
res = gdk_pixbuf_loader_get_pixbuf (loader);
g_object_ref (res);
}
g_object_unref (loader);
g_free (data);
}
}
}
if (!res)
{
if (error)
{
g_warning ("%s\n", error->message);
g_error_free (error);
}
else
g_warning ("incorrect data uri");
}
return res;
}
static GdkPixbuf * static GdkPixbuf *
impl_load_pixbuf_file (GFile *file, impl_load_pixbuf_file (const char *uri,
int available_width, int available_width,
int available_height, int available_height,
int scale, int scale,
GError **error) GError **error)
{ {
GdkPixbuf *pixbuf = NULL; GdkPixbuf *pixbuf = NULL;
GFile *file;
char *contents = NULL; char *contents = NULL;
gsize size; gsize size;
if (g_str_has_prefix (uri, "data:"))
return decode_image (uri);
file = g_file_new_for_uri (uri);
if (g_file_load_contents (file, NULL, &contents, &size, NULL, error)) if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
{ {
pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size, pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
@ -424,6 +490,7 @@ impl_load_pixbuf_file (GFile *file,
error); error);
} }
g_object_unref (file);
g_free (contents); g_free (contents);
return pixbuf; return pixbuf;
@ -440,9 +507,9 @@ load_pixbuf_thread (GSimpleAsyncResult *result,
data = g_async_result_get_user_data (G_ASYNC_RESULT (result)); data = g_async_result_get_user_data (G_ASYNC_RESULT (result));
g_assert (data != NULL); g_assert (data != NULL);
g_assert (data->file != NULL); g_assert (data->uri != NULL);
pixbuf = impl_load_pixbuf_file (data->file, data->width, data->height, data->scale, &error); pixbuf = impl_load_pixbuf_file (data->uri, data->width, data->height, data->scale, &error);
if (error != NULL) if (error != NULL)
{ {
@ -580,7 +647,7 @@ static void
load_texture_async (StTextureCache *cache, load_texture_async (StTextureCache *cache,
AsyncTextureLoadData *data) AsyncTextureLoadData *data)
{ {
if (data->file) if (data->uri)
{ {
GSimpleAsyncResult *result; GSimpleAsyncResult *result;
result = g_simple_async_result_new (G_OBJECT (cache), on_pixbuf_loaded, data, load_texture_async); result = g_simple_async_result_new (G_OBJECT (cache), on_pixbuf_loaded, data, load_texture_async);
@ -947,43 +1014,46 @@ file_changed_cb (GFileMonitor *monitor,
gpointer user_data) gpointer user_data)
{ {
StTextureCache *cache = user_data; StTextureCache *cache = user_data;
char *key; char *uri, *key;
guint file_hash;
if (event_type != G_FILE_MONITOR_EVENT_CHANGED) if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
return; return;
file_hash = g_file_hash (file); uri = g_file_get_uri (file);
key = g_strdup_printf (CACHE_PREFIX_FILE "%u", file_hash); key = g_strconcat (CACHE_PREFIX_URI, uri, NULL);
g_hash_table_remove (cache->priv->keyed_cache, key); g_hash_table_remove (cache->priv->keyed_cache, key);
g_free (key); g_free (key);
key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", file_hash); key = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL);
g_hash_table_remove (cache->priv->keyed_cache, key); g_hash_table_remove (cache->priv->keyed_cache, key);
g_free (key); g_free (key);
g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, file); g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, uri);
g_free (uri);
} }
static void static void
ensure_monitor_for_file (StTextureCache *cache, ensure_monitor_for_uri (StTextureCache *cache,
GFile *file) const gchar *uri)
{ {
StTextureCachePrivate *priv = cache->priv; StTextureCachePrivate *priv = cache->priv;
GFile *file = g_file_new_for_uri (uri);
if (g_hash_table_lookup (priv->file_monitors, file) == NULL) if (g_hash_table_lookup (priv->file_monitors, uri) == NULL)
{ {
GFileMonitor *monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, GFileMonitor *monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE,
NULL, NULL); NULL, NULL);
g_signal_connect (monitor, "changed", g_signal_connect (monitor, "changed",
G_CALLBACK (file_changed_cb), cache); G_CALLBACK (file_changed_cb), cache);
g_hash_table_insert (priv->file_monitors, g_object_ref (file), monitor); g_hash_table_insert (priv->file_monitors, g_strdup (uri), monitor);
} }
g_object_unref (file);
} }
typedef struct { typedef struct {
GFile *gfile; gchar *path;
gint grid_width, grid_height; gint grid_width, grid_height;
gint scale_factor; gint scale_factor;
ClutterActor *actor; ClutterActor *actor;
@ -995,7 +1065,7 @@ static void
on_data_destroy (gpointer data) on_data_destroy (gpointer data)
{ {
AsyncImageData *d = (AsyncImageData *)data; AsyncImageData *d = (AsyncImageData *)data;
g_object_unref (d->gfile); g_free (d->path);
g_object_unref (d->actor); g_object_unref (d->actor);
g_free (d); g_free (d);
} }
@ -1068,7 +1138,7 @@ load_sliced_image (GSimpleAsyncResult *result,
loader = gdk_pixbuf_loader_new (); loader = gdk_pixbuf_loader_new ();
g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), data); g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), data);
if (!g_file_load_contents (data->gfile, NULL, &buffer, &length, NULL, NULL)) if (!g_file_get_contents (data->path, &buffer, &length, NULL))
goto out; goto out;
if (!gdk_pixbuf_loader_write (loader, (const guchar *) buffer, length, NULL)) if (!gdk_pixbuf_loader_write (loader, (const guchar *) buffer, length, NULL))
@ -1103,7 +1173,7 @@ load_sliced_image (GSimpleAsyncResult *result,
/** /**
* st_texture_cache_load_sliced_image: * st_texture_cache_load_sliced_image:
* @cache: A #StTextureCache * @cache: A #StTextureCache
* @file: A #GFile * @path: Path to a filename
* @grid_width: Width in pixels * @grid_width: Width in pixels
* @grid_height: Height in pixels * @grid_height: Height in pixels
* @scale: Scale factor of the display * @scale: Scale factor of the display
@ -1119,7 +1189,7 @@ load_sliced_image (GSimpleAsyncResult *result,
*/ */
ClutterActor * ClutterActor *
st_texture_cache_load_sliced_image (StTextureCache *cache, st_texture_cache_load_sliced_image (StTextureCache *cache,
GFile *file, const gchar *path,
gint grid_width, gint grid_width,
gint grid_height, gint grid_height,
gint scale, gint scale,
@ -1134,7 +1204,7 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
data->grid_width = grid_width; data->grid_width = grid_width;
data->grid_height = grid_height; data->grid_height = grid_height;
data->scale_factor = scale; data->scale_factor = scale;
data->gfile = g_object_ref (file); data->path = g_strdup (path);
data->actor = actor; data->actor = actor;
data->load_callback = load_callback; data->load_callback = load_callback;
data->load_callback_data = user_data; data->load_callback_data = user_data;
@ -1151,9 +1221,9 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
} }
/** /**
* st_texture_cache_load_file_async: * st_texture_cache_load_uri_async:
* @cache: The texture cache instance * @cache: The texture cache instance
* @file: a #GFile of the image file from which to create a pixbuf * @uri: uri of the image file from which to create a pixbuf
* @available_width: available width for the image, can be -1 if not limited * @available_width: available width for the image, can be -1 if not limited
* @available_height: available height for the image, can be -1 if not limited * @available_height: available height for the image, can be -1 if not limited
* @scale: scale factor of the display * @scale: scale factor of the display
@ -1165,18 +1235,18 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
* Return value: (transfer none): A new #ClutterActor with no image loaded initially. * Return value: (transfer none): A new #ClutterActor with no image loaded initially.
*/ */
ClutterActor * ClutterActor *
st_texture_cache_load_file_async (StTextureCache *cache, st_texture_cache_load_uri_async (StTextureCache *cache,
GFile *file, const gchar *uri,
int available_width, int available_width,
int available_height, int available_height,
int scale) int scale)
{ {
ClutterActor *texture; ClutterActor *texture;
AsyncTextureLoadData *request; AsyncTextureLoadData *request;
StTextureCachePolicy policy; StTextureCachePolicy policy;
gchar *key; gchar *key;
key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file)); key = g_strconcat (CACHE_PREFIX_URI, uri, NULL);
policy = ST_TEXTURE_CACHE_POLICY_NONE; /* XXX */ policy = ST_TEXTURE_CACHE_POLICY_NONE; /* XXX */
@ -1194,7 +1264,7 @@ st_texture_cache_load_file_async (StTextureCache *cache,
request->cache = cache; request->cache = cache;
/* Transfer ownership of key */ /* Transfer ownership of key */
request->key = key; request->key = key;
request->file = g_object_ref (file); request->uri = g_strdup (uri);
request->policy = policy; request->policy = policy;
request->width = available_width; request->width = available_width;
request->height = available_height; request->height = available_height;
@ -1203,31 +1273,31 @@ st_texture_cache_load_file_async (StTextureCache *cache,
load_texture_async (cache, request); load_texture_async (cache, request);
} }
ensure_monitor_for_file (cache, file); ensure_monitor_for_uri (cache, uri);
return CLUTTER_ACTOR (texture); return CLUTTER_ACTOR (texture);
} }
static CoglTexture * static CoglTexture *
st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache, st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
StTextureCachePolicy policy, StTextureCachePolicy policy,
GFile *file, const gchar *uri,
int available_width, int available_width,
int available_height, int available_height,
int scale, int scale,
GError **error) GError **error)
{ {
CoglTexture *texdata; CoglTexture *texdata;
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
char *key; char *key;
key = g_strdup_printf (CACHE_PREFIX_FILE "%u", g_file_hash (file)); key = g_strconcat (CACHE_PREFIX_URI, uri, NULL);
texdata = g_hash_table_lookup (cache->priv->keyed_cache, key); texdata = g_hash_table_lookup (cache->priv->keyed_cache, key);
if (texdata == NULL) if (texdata == NULL)
{ {
pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error); pixbuf = impl_load_pixbuf_file (uri, available_width, available_height, scale, error);
if (!pixbuf) if (!pixbuf)
goto out; goto out;
@ -1243,7 +1313,7 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
else else
cogl_object_ref (texdata); cogl_object_ref (texdata);
ensure_monitor_for_file (cache, file); ensure_monitor_for_uri (cache, uri);
out: out:
g_free (key); g_free (key);
@ -1251,25 +1321,25 @@ out:
} }
static cairo_surface_t * static cairo_surface_t *
st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache, st_texture_cache_load_uri_sync_to_cairo_surface (StTextureCache *cache,
StTextureCachePolicy policy, StTextureCachePolicy policy,
GFile *file, const gchar *uri,
int available_width, int available_width,
int available_height, int available_height,
int scale, int scale,
GError **error) GError **error)
{ {
cairo_surface_t *surface; cairo_surface_t *surface;
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
char *key; char *key;
key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", g_file_hash (file)); key = g_strconcat (CACHE_PREFIX_URI_FOR_CAIRO, uri, NULL);
surface = g_hash_table_lookup (cache->priv->keyed_cache, key); surface = g_hash_table_lookup (cache->priv->keyed_cache, key);
if (surface == NULL) if (surface == NULL)
{ {
pixbuf = impl_load_pixbuf_file (file, available_width, available_height, scale, error); pixbuf = impl_load_pixbuf_file (uri, available_width, available_height, scale, error);
if (!pixbuf) if (!pixbuf)
goto out; goto out;
@ -1285,7 +1355,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache,
else else
cairo_surface_reference (surface); cairo_surface_reference (surface);
ensure_monitor_for_file (cache, file); ensure_monitor_for_uri (cache, uri);
out: out:
g_free (key); g_free (key);
@ -1295,7 +1365,7 @@ out:
/** /**
* st_texture_cache_load_file_to_cogl_texture: (skip) * st_texture_cache_load_file_to_cogl_texture: (skip)
* @cache: A #StTextureCache * @cache: A #StTextureCache
* @file: A #GFile in supported image format * @file_path: Path to a file in supported image format
* @scale: Scale factor of the display * @scale: Scale factor of the display
* *
* This function synchronously loads the given file path * This function synchronously loads the given file path
@ -1306,30 +1376,35 @@ out:
*/ */
CoglTexture * CoglTexture *
st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache, st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
GFile *file, const gchar *file_path,
gint scale) gint scale)
{ {
CoglTexture *texture; CoglTexture *texture;
GFile *file;
char *uri;
GError *error = NULL; GError *error = NULL;
texture = st_texture_cache_load_file_sync_to_cogl_texture (cache, ST_TEXTURE_CACHE_POLICY_FOREVER, file = g_file_new_for_path (file_path);
file, -1, -1, scale, &error); uri = g_file_get_uri (file);
texture = st_texture_cache_load_uri_sync_to_cogl_texture (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
uri, -1, -1, scale, &error);
g_object_unref (file);
g_free (uri);
if (texture == NULL) if (texture == NULL)
{ {
char *uri = g_file_get_uri (file); g_warning ("Failed to load %s: %s", file_path, error->message);
g_warning ("Failed to load %s: %s", uri, error->message);
g_clear_error (&error); g_clear_error (&error);
g_free (uri); return NULL;
} }
return texture; return texture;
} }
/** /**
* st_texture_cache_load_file_to_cairo_surface: * st_texture_cache_load_file_to_cairo_surface:
* @cache: A #StTextureCache * @cache: A #StTextureCache
* @file: A #GFile in supported image format * @file_path: Path to a file in supported image format
* @scale: Scale factor of the display * @scale: Scale factor of the display
* *
* This function synchronously loads the given file path * This function synchronously loads the given file path
@ -1340,23 +1415,28 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
*/ */
cairo_surface_t * cairo_surface_t *
st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache, st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
GFile *file, const gchar *file_path,
gint scale) gint scale)
{ {
cairo_surface_t *surface; cairo_surface_t *surface;
GFile *file;
char *uri;
GError *error = NULL; GError *error = NULL;
surface = st_texture_cache_load_file_sync_to_cairo_surface (cache, ST_TEXTURE_CACHE_POLICY_FOREVER, file = g_file_new_for_path (file_path);
file, -1, -1, scale, &error); uri = g_file_get_uri (file);
surface = st_texture_cache_load_uri_sync_to_cairo_surface (cache, ST_TEXTURE_CACHE_POLICY_FOREVER,
uri, -1, -1, scale, &error);
g_object_unref (file);
g_free (uri);
if (surface == NULL) if (surface == NULL)
{ {
char *uri = g_file_get_uri (file); g_warning ("Failed to load %s: %s", file_path, error->message);
g_warning ("Failed to load %s: %s", uri, error->message);
g_clear_error (&error); g_clear_error (&error);
g_free (uri); return NULL;
} }
return surface; return surface;
} }

View File

@ -70,7 +70,7 @@ StTextureCache* st_texture_cache_get_default (void);
ClutterActor * ClutterActor *
st_texture_cache_load_sliced_image (StTextureCache *cache, st_texture_cache_load_sliced_image (StTextureCache *cache,
GFile *file, const gchar *path,
gint grid_width, gint grid_width,
gint grid_height, gint grid_height,
gint scale, gint scale,
@ -87,18 +87,18 @@ ClutterActor *st_texture_cache_load_gicon (StTextureCache *cache,
gint size, gint size,
gint scale); gint scale);
ClutterActor *st_texture_cache_load_file_async (StTextureCache *cache, ClutterActor *st_texture_cache_load_uri_async (StTextureCache *cache,
GFile *file, const gchar *uri,
int available_width, int available_width,
int available_height, int available_height,
int scale); int scale);
CoglTexture *st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache, CoglTexture *st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
GFile *file, const gchar *file_path,
gint scale); gint scale);
cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache, cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
GFile *file, const gchar *file_path,
gint scale); gint scale);
/** /**

View File

@ -600,7 +600,7 @@ create_cairo_pattern_of_background_image (StThemeNode *node,
cairo_pattern_t *pattern; cairo_pattern_t *pattern;
cairo_content_t content; cairo_content_t content;
cairo_matrix_t matrix; cairo_matrix_t matrix;
GFile *file; const char *file;
StTextureCache *texture_cache; StTextureCache *texture_cache;
@ -1037,7 +1037,7 @@ st_theme_node_prerender_background (StThemeNode *node,
} }
else else
{ {
GFile *background_image; const char *background_image;
background_image = st_theme_node_get_background_image (node); background_image = st_theme_node_get_background_image (node);
@ -1303,14 +1303,14 @@ st_theme_node_load_border_image (StThemeNode *node)
if (border_image == NULL) if (border_image == NULL)
goto out; goto out;
GFile *file; const char *filename;
file = st_border_image_get_file (border_image); filename = st_border_image_get_filename (border_image);
int scale_factor; int scale_factor;
g_object_get (node->context, "scale-factor", &scale_factor, NULL); g_object_get (node->context, "scale-factor", &scale_factor, NULL);
node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (), node->border_slices_texture = st_texture_cache_load_file_to_cogl_texture (st_texture_cache_get_default (),
file, scale_factor); filename, scale_factor);
if (node->border_slices_texture == COGL_INVALID_HANDLE) if (node->border_slices_texture == COGL_INVALID_HANDLE)
goto out; goto out;
@ -1348,7 +1348,7 @@ st_theme_node_load_background_image (StThemeNode *node)
{ {
if (node->background_texture == COGL_INVALID_HANDLE) if (node->background_texture == COGL_INVALID_HANDLE)
{ {
GFile *background_image; const char *background_image;
StShadow *background_image_shadow_spec; StShadow *background_image_shadow_spec;
background_image = st_theme_node_get_background_image (node); background_image = st_theme_node_get_background_image (node);

View File

@ -68,7 +68,7 @@ struct _StThemeNode {
int transition_duration; int transition_duration;
GFile *background_image; char *background_image;
StBorderImage *border_image; StBorderImage *border_image;
StShadow *box_shadow; StShadow *box_shadow;
StShadow *background_image_shadow; StShadow *background_image_shadow;

View File

@ -158,10 +158,7 @@ st_theme_node_finalize (GObject *object)
} }
if (node->background_image) if (node->background_image)
{ g_free (node->background_image);
g_object_unref (node->background_image);
node->background_image = NULL;
}
if (node->background_texture != COGL_INVALID_HANDLE) if (node->background_texture != COGL_INVALID_HANDLE)
cogl_handle_unref (node->background_texture); cogl_handle_unref (node->background_texture);
@ -908,7 +905,7 @@ st_theme_node_get_double (StThemeNode *node,
* parent's parent, and so forth. Note that if the property has a * parent's parent, and so forth. Note that if the property has a
* value of 'inherit' it will be inherited even if %FALSE is passed * value of 'inherit' it will be inherited even if %FALSE is passed
* in for @inherit; this only affects the default behavior for inheritance. * in for @inherit; this only affects the default behavior for inheritance.
* @file: (out) (transfer full): location to store the newly allocated value that was * @value: (out): location to store the newly allocated value that was
* determined. If the property is not found, the value in this location * determined. If the property is not found, the value in this location
* will not be changed. * will not be changed.
* *
@ -923,7 +920,7 @@ gboolean
st_theme_node_lookup_url (StThemeNode *node, st_theme_node_lookup_url (StThemeNode *node,
const char *property_name, const char *property_name,
gboolean inherit, gboolean inherit,
GFile **file) char **value)
{ {
gboolean result = FALSE; gboolean result = FALSE;
int i; int i;
@ -938,6 +935,7 @@ st_theme_node_lookup_url (StThemeNode *node,
{ {
CRTerm *term = decl->value; CRTerm *term = decl->value;
CRStyleSheet *base_stylesheet; CRStyleSheet *base_stylesheet;
GFile *file;
if (term->type != TERM_URI && term->type != TERM_STRING) if (term->type != TERM_URI && term->type != TERM_STRING)
continue; continue;
@ -947,21 +945,23 @@ st_theme_node_lookup_url (StThemeNode *node,
else else
base_stylesheet = NULL; base_stylesheet = NULL;
*file = _st_theme_resolve_url (node->theme, file = _st_theme_resolve_url (node->theme,
base_stylesheet, base_stylesheet,
decl->value->content.str->stryng->str); decl->value->content.str->stryng->str);
*value = g_file_get_path (file);
g_object_unref (file);
result = TRUE; result = TRUE;
break; break;
} }
} }
if (!result && inherit && node->parent_node) if (!result && inherit && node->parent_node)
result = st_theme_node_lookup_url (node->parent_node, property_name, inherit, file); result = st_theme_node_lookup_url (node->parent_node, property_name, inherit, value);
return result; return result;
} }
/** /*
* st_theme_node_get_url: * st_theme_node_get_url:
* @node: a #StThemeNode * @node: a #StThemeNode
* @property_name: The name of the string property * @property_name: The name of the string property
@ -972,18 +972,18 @@ st_theme_node_lookup_url (StThemeNode *node,
* and lets you handle the case where the theme does not specify the * and lets you handle the case where the theme does not specify the
* indicated value. * indicated value.
* *
* Returns: (transfer full): the newly allocated value if found. * Return value: the newly allocated value if found.
* If @property_name is not found, a warning will be logged and %NULL * If @property_name is not found, a warning will be logged and %NULL
* will be returned. * will be returned.
*/ */
GFile * char *
st_theme_node_get_url (StThemeNode *node, st_theme_node_get_url (StThemeNode *node,
const char *property_name) const char *property_name)
{ {
GFile *file; char *value;
if (st_theme_node_lookup_url (node, property_name, FALSE, &file)) if (st_theme_node_lookup_url (node, property_name, FALSE, &value))
return file; return value;
else else
{ {
g_warning ("Did not find string property '%s'", property_name); g_warning ("Did not find string property '%s'", property_name);
@ -1926,7 +1926,8 @@ _st_theme_node_ensure_background (StThemeNode *node)
CRTerm *term; CRTerm *term;
/* background: property sets all terms to specified or default values */ /* background: property sets all terms to specified or default values */
node->background_color = TRANSPARENT_COLOR; node->background_color = TRANSPARENT_COLOR;
g_clear_object (&node->background_image); g_free (node->background_image);
node->background_image = NULL;
node->background_position_set = FALSE; node->background_position_set = FALSE;
node->background_size = ST_BACKGROUND_SIZE_AUTO; node->background_size = ST_BACKGROUND_SIZE_AUTO;
@ -1942,7 +1943,7 @@ _st_theme_node_ensure_background (StThemeNode *node)
if (node->parent_node) if (node->parent_node)
{ {
st_theme_node_get_background_color (node->parent_node, &node->background_color); st_theme_node_get_background_color (node->parent_node, &node->background_color);
node->background_image = g_object_ref (st_theme_node_get_background_image (node->parent_node)); node->background_image = g_strdup (st_theme_node_get_background_image (node->parent_node));
} }
} }
else if (term_is_none (term)) else if (term_is_none (term))
@ -1963,7 +1964,8 @@ _st_theme_node_ensure_background (StThemeNode *node)
base_stylesheet, base_stylesheet,
term->content.str->stryng->str); term->content.str->stryng->str);
node->background_image = file; node->background_image = g_file_get_path (file);
g_object_unref (file);
} }
} }
} }
@ -2060,25 +2062,30 @@ _st_theme_node_ensure_background (StThemeNode *node)
if (decl->value->type == TERM_URI) if (decl->value->type == TERM_URI)
{ {
CRStyleSheet *base_stylesheet; CRStyleSheet *base_stylesheet;
GFile *file;
if (decl->parent_statement != NULL) if (decl->parent_statement != NULL)
base_stylesheet = decl->parent_statement->parent_sheet; base_stylesheet = decl->parent_statement->parent_sheet;
else else
base_stylesheet = NULL; base_stylesheet = NULL;
g_clear_object (&node->background_image); g_free (node->background_image);
node->background_image = _st_theme_resolve_url (node->theme, file = _st_theme_resolve_url (node->theme,
base_stylesheet, base_stylesheet,
decl->value->content.str->stryng->str); decl->value->content.str->stryng->str);
node->background_image = g_file_get_path (file);
g_object_unref (file);
} }
else if (term_is_inherit (decl->value)) else if (term_is_inherit (decl->value))
{ {
g_clear_object (&node->background_image); g_free (node->background_image);
node->background_image = g_object_ref (st_theme_node_get_background_image (node->parent_node)); node->background_image = g_strdup (st_theme_node_get_background_image (node->parent_node));
} }
else if (term_is_none (decl->value)) else if (term_is_none (decl->value))
{ {
g_clear_object (&node->background_image); g_free (node->background_image);
node->background_image = NULL;
} }
} }
else if (strcmp (property_name, "-gradient-direction") == 0) else if (strcmp (property_name, "-gradient-direction") == 0)
@ -2135,13 +2142,7 @@ st_theme_node_get_background_color (StThemeNode *node,
*color = node->background_color; *color = node->background_color;
} }
/** const char *
* st_theme_node_get_background_image:
* @node: a #StThemeNode
*
* Returns: (transfer none): @node's background image.
*/
GFile *
st_theme_node_get_background_image (StThemeNode *node) st_theme_node_get_background_image (StThemeNode *node)
{ {
g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL); g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
@ -2893,6 +2894,7 @@ st_theme_node_get_border_image (StThemeNode *node)
int border_left; int border_left;
GFile *file; GFile *file;
char *filename;
/* Support border-image: none; to suppress a previously specified border image */ /* Support border-image: none; to suppress a previously specified border image */
if (term_is_none (term)) if (term_is_none (term))
@ -2971,15 +2973,17 @@ st_theme_node_get_border_image (StThemeNode *node)
base_stylesheet = NULL; base_stylesheet = NULL;
file = _st_theme_resolve_url (node->theme, base_stylesheet, url); file = _st_theme_resolve_url (node->theme, base_stylesheet, url);
filename = g_file_get_path (file);
g_object_unref (file);
if (file == NULL) if (filename == NULL)
goto next_property; goto next_property;
node->border_image = st_border_image_new (file, node->border_image = st_border_image_new (filename,
border_top, border_right, border_bottom, border_left, border_top, border_right, border_bottom, border_left,
scale_factor); scale_factor);
g_object_unref (file); g_free (filename);
return node->border_image; return node->border_image;
} }
@ -3849,9 +3853,7 @@ st_theme_node_paint_equal (StThemeNode *node,
!clutter_color_equal (&node->background_gradient_end, &other->background_gradient_end)) !clutter_color_equal (&node->background_gradient_end, &other->background_gradient_end))
return FALSE; return FALSE;
if ((node->background_image != NULL) && if (g_strcmp0 (node->background_image, other->background_image) != 0)
(other->background_image != NULL) &&
!g_file_equal (node->background_image, other->background_image))
return FALSE; return FALSE;
_st_theme_node_ensure_geometry (node); _st_theme_node_ensure_geometry (node);

View File

@ -162,7 +162,7 @@ gboolean st_theme_node_lookup_shadow (StThemeNode *node,
gboolean st_theme_node_lookup_url (StThemeNode *node, gboolean st_theme_node_lookup_url (StThemeNode *node,
const char *property_name, const char *property_name,
gboolean inherit, gboolean inherit,
GFile **file); char **value);
/* Easier-to-use variants of the above, for application-level use */ /* Easier-to-use variants of the above, for application-level use */
void st_theme_node_get_color (StThemeNode *node, void st_theme_node_get_color (StThemeNode *node,
@ -174,7 +174,7 @@ gdouble st_theme_node_get_length (StThemeNode *node,
const char *property_name); const char *property_name);
StShadow *st_theme_node_get_shadow (StThemeNode *node, StShadow *st_theme_node_get_shadow (StThemeNode *node,
const char *property_name); const char *property_name);
GFile *st_theme_node_get_url (StThemeNode *node, char *st_theme_node_get_url (StThemeNode *node,
const char *property_name); const char *property_name);
/* Specific getters for particular properties: cached /* Specific getters for particular properties: cached
@ -188,7 +188,7 @@ void st_theme_node_get_background_gradient (StThemeNode *node,
ClutterColor *start, ClutterColor *start,
ClutterColor *end); ClutterColor *end);
GFile *st_theme_node_get_background_image (StThemeNode *node); const char *st_theme_node_get_background_image (StThemeNode *node);
int st_theme_node_get_border_width (StThemeNode *node, int st_theme_node_get_border_width (StThemeNode *node,
StSide side); StSide side);

View File

@ -60,13 +60,13 @@ struct _StTheme
{ {
GObject parent; GObject parent;
GFile *application_stylesheet; char *application_stylesheet;
GFile *default_stylesheet; char *default_stylesheet;
GFile *theme_stylesheet; char *theme_stylesheet;
GSList *custom_stylesheets; GSList *custom_stylesheets;
GHashTable *stylesheets_by_file; GHashTable *stylesheets_by_filename;
GHashTable *files_by_stylesheet; GHashTable *filenames_by_stylesheet;
CRCascade *cascade; CRCascade *cascade;
}; };
@ -98,25 +98,12 @@ G_DEFINE_TYPE (StTheme, st_theme, G_TYPE_OBJECT)
#define strqcmp(str,lit,lit_len) \ #define strqcmp(str,lit,lit_len) \
(strlen (str) != (lit_len) || memcmp (str, lit, lit_len)) (strlen (str) != (lit_len) || memcmp (str, lit, lit_len))
static gboolean
file_equal0 (GFile *file1,
GFile *file2)
{
if (file1 == file2)
return TRUE;
if ((file1 == NULL) || (file2 == NULL))
return FALSE;
return g_file_equal (file1, file2);
}
static void static void
st_theme_init (StTheme *theme) st_theme_init (StTheme *theme)
{ {
theme->stylesheets_by_file = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, theme->stylesheets_by_filename = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_object_unref, (GDestroyNotify)cr_stylesheet_unref); (GDestroyNotify)g_free, (GDestroyNotify)cr_stylesheet_unref);
theme->files_by_stylesheet = g_hash_table_new (g_direct_hash, g_direct_equal); theme->filenames_by_stylesheet = g_hash_table_new (g_direct_hash, g_direct_equal);
} }
static void static void
@ -137,10 +124,10 @@ st_theme_class_init (StThemeClass *klass)
*/ */
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_APPLICATION_STYLESHEET, PROP_APPLICATION_STYLESHEET,
g_param_spec_object ("application-stylesheet", g_param_spec_string ("application-stylesheet",
"Application Stylesheet", "Application Stylesheet",
"Stylesheet with application-specific styling", "Stylesheet with application-specific styling",
G_TYPE_FILE, NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
/** /**
@ -151,10 +138,10 @@ st_theme_class_init (StThemeClass *klass)
*/ */
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_THEME_STYLESHEET, PROP_THEME_STYLESHEET,
g_param_spec_object ("theme-stylesheet", g_param_spec_string ("theme-stylesheet",
"Theme Stylesheet", "Theme Stylesheet",
"Stylesheet with theme-specific styling", "Stylesheet with theme-specific styling",
G_TYPE_FILE, NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
/** /**
@ -165,10 +152,10 @@ st_theme_class_init (StThemeClass *klass)
*/ */
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_DEFAULT_STYLESHEET, PROP_DEFAULT_STYLESHEET,
g_param_spec_object ("default-stylesheet", g_param_spec_string ("default-stylesheet",
"Default Stylesheet", "Default Stylesheet",
"Stylesheet with global default styling", "Stylesheet with global default styling",
G_TYPE_FILE, NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
signals[STYLESHEETS_CHANGED] = signals[STYLESHEETS_CHANGED] =
@ -181,32 +168,23 @@ st_theme_class_init (StThemeClass *klass)
} }
static CRStyleSheet * static CRStyleSheet *
parse_stylesheet (GFile *file, parse_stylesheet (const char *filename,
GError **error) GError **error)
{ {
enum CRStatus status; enum CRStatus status;
CRStyleSheet *stylesheet; CRStyleSheet *stylesheet;
char *contents;
gsize length;
if (file == NULL) if (filename == NULL)
return NULL; return NULL;
if (!g_file_load_contents (file, NULL, &contents, &length, NULL, error)) status = cr_om_parser_simply_parse_file ((const guchar *) filename,
return NULL; CR_UTF_8,
&stylesheet);
status = cr_om_parser_simply_parse_buf ((const guchar *) contents,
length,
CR_UTF_8,
&stylesheet);
g_free (contents);
if (status != CR_OK) if (status != CR_OK)
{ {
char *uri = g_file_get_uri (file);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error parsing stylesheet '%s'; errcode:%d", uri, status); "Error parsing stylesheet '%s'; errcode:%d", filename, status);
g_free (uri);
return NULL; return NULL;
} }
@ -225,12 +203,12 @@ _st_theme_parse_declaration_list (const char *str)
/* Just g_warning for now until we have something nicer to do */ /* Just g_warning for now until we have something nicer to do */
static CRStyleSheet * static CRStyleSheet *
parse_stylesheet_nofail (GFile *file) parse_stylesheet_nofail (const char *filename)
{ {
GError *error = NULL; GError *error = NULL;
CRStyleSheet *result; CRStyleSheet *result;
result = parse_stylesheet (file, &error); result = parse_stylesheet (filename, &error);
if (error) if (error)
{ {
g_warning ("%s", error->message); g_warning ("%s", error->message);
@ -241,33 +219,35 @@ parse_stylesheet_nofail (GFile *file)
static void static void
insert_stylesheet (StTheme *theme, insert_stylesheet (StTheme *theme,
GFile *file, const char *filename,
CRStyleSheet *stylesheet) CRStyleSheet *stylesheet)
{ {
char *filename_copy;
if (stylesheet == NULL) if (stylesheet == NULL)
return; return;
g_object_ref (file); filename_copy = g_strdup(filename);
cr_stylesheet_ref (stylesheet); cr_stylesheet_ref (stylesheet);
g_hash_table_insert (theme->stylesheets_by_file, file, stylesheet); g_hash_table_insert (theme->stylesheets_by_filename, filename_copy, stylesheet);
g_hash_table_insert (theme->files_by_stylesheet, stylesheet, file); g_hash_table_insert (theme->filenames_by_stylesheet, stylesheet, filename_copy);
} }
gboolean gboolean
st_theme_load_stylesheet (StTheme *theme, st_theme_load_stylesheet (StTheme *theme,
GFile *file, const char *path,
GError **error) GError **error)
{ {
CRStyleSheet *stylesheet; CRStyleSheet *stylesheet;
stylesheet = parse_stylesheet (file, error); stylesheet = parse_stylesheet (path, error);
if (!stylesheet) if (!stylesheet)
return FALSE; return FALSE;
stylesheet->app_data = GUINT_TO_POINTER (TRUE); stylesheet->app_data = GUINT_TO_POINTER (TRUE);
insert_stylesheet (theme, file, stylesheet); insert_stylesheet (theme, path, stylesheet);
cr_stylesheet_ref (stylesheet); cr_stylesheet_ref (stylesheet);
theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet); theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet);
g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0); g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0);
@ -277,11 +257,11 @@ st_theme_load_stylesheet (StTheme *theme,
void void
st_theme_unload_stylesheet (StTheme *theme, st_theme_unload_stylesheet (StTheme *theme,
GFile *file) const char *path)
{ {
CRStyleSheet *stylesheet; CRStyleSheet *stylesheet;
stylesheet = g_hash_table_lookup (theme->stylesheets_by_file, file); stylesheet = g_hash_table_lookup (theme->stylesheets_by_filename, path);
if (!stylesheet) if (!stylesheet)
return; return;
@ -289,8 +269,8 @@ st_theme_unload_stylesheet (StTheme *theme,
return; return;
theme->custom_stylesheets = g_slist_remove (theme->custom_stylesheets, stylesheet); theme->custom_stylesheets = g_slist_remove (theme->custom_stylesheets, stylesheet);
g_hash_table_remove (theme->stylesheets_by_file, file); g_hash_table_remove (theme->stylesheets_by_filename, path);
g_hash_table_remove (theme->files_by_stylesheet, stylesheet); g_hash_table_remove (theme->filenames_by_stylesheet, stylesheet);
cr_stylesheet_unref (stylesheet); cr_stylesheet_unref (stylesheet);
g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0); g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0);
} }
@ -299,7 +279,7 @@ st_theme_unload_stylesheet (StTheme *theme,
* st_theme_get_custom_stylesheets: * st_theme_get_custom_stylesheets:
* @theme: an #StTheme * @theme: an #StTheme
* *
* Returns: (transfer full) (element-type GFile): the list of stylesheet files * Returns: (transfer full) (element-type utf8): the list of stylesheet filenames
* that were loaded with st_theme_load_stylesheet() * that were loaded with st_theme_load_stylesheet()
*/ */
GSList* GSList*
@ -311,9 +291,9 @@ st_theme_get_custom_stylesheets (StTheme *theme)
for (iter = theme->custom_stylesheets; iter; iter = iter->next) for (iter = theme->custom_stylesheets; iter; iter = iter->next)
{ {
CRStyleSheet *stylesheet = iter->data; CRStyleSheet *stylesheet = iter->data;
GFile *file = g_hash_table_lookup (theme->files_by_stylesheet, stylesheet); gchar *filename = g_hash_table_lookup (theme->filenames_by_stylesheet, stylesheet);
result = g_slist_prepend (result, g_object_ref (file)); result = g_slist_prepend (result, g_strdup (filename));
} }
return result; return result;
@ -354,12 +334,12 @@ st_theme_finalize (GObject * object)
g_slist_free (theme->custom_stylesheets); g_slist_free (theme->custom_stylesheets);
theme->custom_stylesheets = NULL; theme->custom_stylesheets = NULL;
g_hash_table_destroy (theme->stylesheets_by_file); g_hash_table_destroy (theme->stylesheets_by_filename);
g_hash_table_destroy (theme->files_by_stylesheet); g_hash_table_destroy (theme->filenames_by_stylesheet);
g_clear_object (&theme->application_stylesheet); g_free (theme->application_stylesheet);
g_clear_object (&theme->theme_stylesheet); g_free (theme->theme_stylesheet);
g_clear_object (&theme->default_stylesheet); g_free (theme->default_stylesheet);
if (theme->cascade) if (theme->cascade)
{ {
@ -382,39 +362,36 @@ st_theme_set_property (GObject *object,
{ {
case PROP_APPLICATION_STYLESHEET: case PROP_APPLICATION_STYLESHEET:
{ {
GFile *file = g_value_get_object (value); const char *path = g_value_get_string (value);
if (!file_equal0 (file, theme->application_stylesheet)) if (path != theme->application_stylesheet)
{ {
g_clear_object (&theme->application_stylesheet); g_free (theme->application_stylesheet);
if (file != NULL) theme->application_stylesheet = g_strdup (path);
theme->application_stylesheet = g_object_ref (file);
} }
break; break;
} }
case PROP_THEME_STYLESHEET: case PROP_THEME_STYLESHEET:
{ {
GFile *file = g_value_get_object (value); const char *path = g_value_get_string (value);
if (!file_equal0 (file, theme->theme_stylesheet)) if (path != theme->theme_stylesheet)
{ {
g_clear_object (&theme->theme_stylesheet); g_free (theme->theme_stylesheet);
if (file != NULL) theme->theme_stylesheet = g_strdup (path);
theme->theme_stylesheet = g_object_ref (file);
} }
break; break;
} }
case PROP_DEFAULT_STYLESHEET: case PROP_DEFAULT_STYLESHEET:
{ {
GFile *file = g_value_get_object (value); const char *path = g_value_get_string (value);
if (!file_equal0 (file, theme->default_stylesheet)) if (path != theme->default_stylesheet)
{ {
g_clear_object (&theme->default_stylesheet); g_free (theme->default_stylesheet);
if (file != NULL) theme->default_stylesheet = g_strdup (path);
theme->default_stylesheet = g_object_ref (file);
} }
break; break;
@ -436,13 +413,13 @@ st_theme_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_APPLICATION_STYLESHEET: case PROP_APPLICATION_STYLESHEET:
g_value_set_object (value, theme->application_stylesheet); g_value_set_string (value, theme->application_stylesheet);
break; break;
case PROP_THEME_STYLESHEET: case PROP_THEME_STYLESHEET:
g_value_set_object (value, theme->theme_stylesheet); g_value_set_string (value, theme->theme_stylesheet);
break; break;
case PROP_DEFAULT_STYLESHEET: case PROP_DEFAULT_STYLESHEET:
g_value_set_object (value, theme->default_stylesheet); g_value_set_string (value, theme->default_stylesheet);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -462,9 +439,9 @@ st_theme_get_property (GObject *object,
* Return value: the newly created theme object * Return value: the newly created theme object
**/ **/
StTheme * StTheme *
st_theme_new (GFile *application_stylesheet, st_theme_new (const char *application_stylesheet,
GFile *theme_stylesheet, const char *theme_stylesheet,
GFile *default_stylesheet) const char *default_stylesheet)
{ {
StTheme *theme = g_object_new (ST_TYPE_THEME, StTheme *theme = g_object_new (ST_TYPE_THEME,
"application-stylesheet", application_stylesheet, "application-stylesheet", application_stylesheet,
@ -875,19 +852,26 @@ add_matched_properties (StTheme *a_this,
if (import_rule->sheet == NULL) if (import_rule->sheet == NULL)
{ {
GFile *file = NULL; char *filename = NULL;
if (import_rule->url->stryng && import_rule->url->stryng->str) if (import_rule->url->stryng && import_rule->url->stryng->str)
{ {
GFile *file;
file = _st_theme_resolve_url (a_this, file = _st_theme_resolve_url (a_this,
a_nodesheet, a_nodesheet,
import_rule->url->stryng->str); import_rule->url->stryng->str);
import_rule->sheet = parse_stylesheet (file, NULL); filename = g_file_get_path (file);
g_object_unref (file);
} }
if (filename)
import_rule->sheet = parse_stylesheet (filename, NULL);
if (import_rule->sheet) if (import_rule->sheet)
{ {
insert_stylesheet (a_this, file, import_rule->sheet); insert_stylesheet (a_this, filename, import_rule->sheet);
/* refcount of stylesheets starts off at zero, so we don't need to unref! */ /* refcount of stylesheets starts off at zero, so we don't need to unref! */
} }
else else
@ -898,8 +882,8 @@ add_matched_properties (StTheme *a_this,
import_rule->sheet = (CRStyleSheet *) - 1; import_rule->sheet = (CRStyleSheet *) - 1;
} }
if (file) if (filename)
g_object_unref (file); g_free (filename);
} }
if (import_rule->sheet != (CRStyleSheet *) - 1) if (import_rule->sheet != (CRStyleSheet *) - 1)
@ -1024,8 +1008,8 @@ _st_theme_get_matched_properties (StTheme *theme,
return props; return props;
} }
/* Resolve an url from an url() reference in a stylesheet into a GFile, /* Resolve an url from an url() reference in a stylesheet into an absolute
* if possible. The resolution here is distinctly lame and * local filename, if possible. The resolution here is distinctly lame and
* will fail on many examples. * will fail on many examples.
*/ */
GFile * GFile *
@ -1034,7 +1018,7 @@ _st_theme_resolve_url (StTheme *theme,
const char *url) const char *url)
{ {
char *scheme; char *scheme;
GFile *resource; GFile *stylesheet, *resource;
if ((scheme = g_uri_parse_scheme (url))) if ((scheme = g_uri_parse_scheme (url)))
{ {
@ -1043,18 +1027,21 @@ _st_theme_resolve_url (StTheme *theme,
} }
else if (base_stylesheet != NULL) else if (base_stylesheet != NULL)
{ {
GFile *base_file = NULL, *parent; const char *base_filename = NULL;
char *dirname;
base_file = g_hash_table_lookup (theme->files_by_stylesheet, base_stylesheet); base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet);
/* This is an internal function, if we get here with /* This is an internal function, if we get here with
a bad @base_stylesheet we have a problem. */ a bad @base_stylesheet we have a problem. */
g_assert (base_file); g_assert (base_filename);
parent = g_file_get_parent (base_file); dirname = g_path_get_dirname (base_filename);
resource = g_file_resolve_relative_path (parent, url); stylesheet = g_file_new_for_path (dirname);
resource = g_file_resolve_relative_path (stylesheet, url);
g_object_unref (parent); g_object_unref (stylesheet);
g_free (dirname);
} }
else else
{ {

View File

@ -47,12 +47,12 @@ typedef struct _StThemeClass StThemeClass;
GType st_theme_get_type (void) G_GNUC_CONST; GType st_theme_get_type (void) G_GNUC_CONST;
StTheme *st_theme_new (GFile *application_stylesheet, StTheme *st_theme_new (const char *application_stylesheet,
GFile *theme_stylesheet, const char *theme_stylesheet,
GFile *default_stylesheet); const char *default_stylesheet);
gboolean st_theme_load_stylesheet (StTheme *theme, GFile *file, GError **error); gboolean st_theme_load_stylesheet (StTheme *theme, const char *path, GError **error);
void st_theme_unload_stylesheet (StTheme *theme, GFile *file); void st_theme_unload_stylesheet (StTheme *theme, const char *path);
GSList *st_theme_get_custom_stylesheets (StTheme *theme); GSList *st_theme_get_custom_stylesheets (StTheme *theme);
G_END_DECLS G_END_DECLS

View File

@ -277,26 +277,26 @@ current_paint_state (StWidget *widget)
static void static void
st_widget_texture_cache_changed (StTextureCache *cache, st_widget_texture_cache_changed (StTextureCache *cache,
GFile *file, const char *uri,
gpointer user_data) gpointer user_data)
{ {
StWidget *actor = ST_WIDGET (user_data); StWidget *actor = ST_WIDGET (user_data);
StThemeNode *node = actor->priv->theme_node; StThemeNode *node = actor->priv->theme_node;
char *path;
gboolean changed = FALSE; gboolean changed = FALSE;
GFile *theme_file;
if (node == NULL) if (node == NULL)
return; return;
theme_file = st_theme_node_get_background_image (node); path = g_filename_from_uri (uri, NULL, NULL);
if ((theme_file != NULL) && g_file_equal (theme_file, file))
if (g_strcmp0 (st_theme_node_get_background_image (node), path) == 0)
{ {
st_theme_node_invalidate_background_image (node); st_theme_node_invalidate_background_image (node);
changed = TRUE; changed = TRUE;
} }
theme_file = st_border_image_get_file (st_theme_node_get_border_image (node)); if (g_strcmp0 (st_border_image_get_filename (st_theme_node_get_border_image (node)), path) == 0)
if ((theme_file != NULL) && g_file_equal (theme_file, file))
{ {
st_theme_node_invalidate_border_image (node); st_theme_node_invalidate_border_image (node);
changed = TRUE; changed = TRUE;
@ -317,6 +317,8 @@ st_widget_texture_cache_changed (StTextureCache *cache,
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor))) if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor)); clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
} }
g_free (path);
} }
static void static void

View File

@ -173,21 +173,17 @@ assert_background_image (StThemeNode *node,
const char *node_description, const char *node_description,
const char *expected) const char *expected)
{ {
GFile *value = st_theme_node_get_background_image (node); const char *value = st_theme_node_get_background_image (node);
GFile *expected_file; if (expected == NULL)
expected = "(null)";
if (value == NULL)
value = "(null)";
if (expected != NULL && value != NULL) if (strcmp (expected, value) != 0)
{ {
expected_file = g_file_new_for_path (expected); g_print ("%s: %s.background-image: expected: %s, got: %s\n",
test, node_description, expected, value);
if (!g_file_equal (expected_file, value)) fail = TRUE;
{
char *uri = g_file_get_uri (expected_file);
g_print ("%s: %s.background-image: expected: %s, got: %s\n",
test, node_description, expected, uri);
fail = TRUE;
g_free (uri);
}
} }
} }
@ -430,16 +426,14 @@ main (int argc, char **argv)
StTheme *theme; StTheme *theme;
StThemeContext *context; StThemeContext *context;
PangoFontDescription *font_desc; PangoFontDescription *font_desc;
GFile *file;
gtk_init (&argc, &argv); gtk_init (&argc, &argv);
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1; return 1;
file = g_file_new_for_path ("st/test-theme.css"); theme = st_theme_new ("st/test-theme.css",
theme = st_theme_new (file, NULL, NULL); NULL, NULL);
g_object_unref (file);
stage = clutter_stage_new (); stage = clutter_stage_new ();
context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage)); context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage));

View File

@ -312,9 +312,6 @@ function test() {
button.label = 'NEVER'; button.label = 'NEVER';
break; break;
case 'NEVER': case 'NEVER':
button.label = 'EXTERNAL';
break;
case 'EXTERNAL':
button.label = 'AUTOMATIC'; button.label = 'AUTOMATIC';
break; break;
} }

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const St = imports.gi.St; const St = imports.gi.St;
@ -11,7 +10,7 @@ function init(stage) {
Environment.init(); Environment.init();
let context = St.ThemeContext.get_for_stage(stage); let context = St.ThemeContext.get_for_stage(stage);
let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css"; let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css";
let theme = new St.Theme({ application_stylesheet: Gio.File.new_for_path(stylesheetPath) }); let theme = new St.Theme({ application_stylesheet: stylesheetPath });
context.set_theme(theme); context.set_theme(theme);
} }