Marco Trevisan (Treviño) has proposed merging
~3v1n0/ubuntu/+source/gnome-shell:upstream/3.28.x into
~ubuntu-desktop/ubuntu/+source/gnome-shell:upstream/3.28.x.
Requested reviews:
Ubuntu Desktop (ubuntu-desktop)
For more details, see:
https://code.launchpad.net/~3v1n0/ubuntu/+source/gnome-shell/+git/gnome-shell/+merge/362054
--
Your team Ubuntu Desktop is requested to review the proposed merge of
~3v1n0/ubuntu/+source/gnome-shell:upstream/3.28.x into
~ubuntu-desktop/ubuntu/+source/gnome-shell:upstream/3.28.x.
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index 481cd3a..a0a4a21 100644
--- a/js/gdm/authPrompt.js
+++ b/js/gdm/authPrompt.js
@@ -242,11 +242,11 @@ var AuthPrompt = new Lang.Class({
this.emit('prompted');
},
- _onVerificationFailed() {
+ _onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null;
this.clear();
- this.updateSensitivity(true);
+ this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
},
@@ -439,6 +439,7 @@ var AuthPrompt = new Lang.Class({
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
this.nextButton.label = _("Next");
+ this._preemptiveAnswer = null;
if (this._userVerifier)
this._userVerifier.cancel();
diff --git a/js/gdm/util.js b/js/gdm/util.js
index 261e1e4..105a320 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -534,12 +534,13 @@ var ShellUserVerifier = new Lang.Class({
_verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset
// the dialog
- // Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
- // go back to the welcome screen.
+ // Otherwise, when in login mode we allow ALLOWED_FAILURES attempts.
+ // After that, we go back to the welcome screen.
this._failCounter++;
let canRetry = retry && this._userName &&
- this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
+ (this._reauthOnly ||
+ this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY));
if (canRetry) {
if (!this.hasPendingMessages) {
@@ -562,7 +563,7 @@ var ShellUserVerifier = new Lang.Class({
}
}
- this.emit('verification-failed');
+ this.emit('verification-failed', canRetry);
},
_onConversationStopped(client, serviceName) {
diff --git a/js/misc/objectManager.js b/js/misc/objectManager.js
index 1ce4f83..1442e3d 100644
--- a/js/misc/objectManager.js
+++ b/js/misc/objectManager.js
@@ -236,11 +236,12 @@ var ObjectManager = new Lang.Class({
_onNameVanished() {
let objectPaths = Object.keys(this._objects);
for (let i = 0; i < objectPaths.length; i++) {
- let object = this._objects[objectPaths];
+ let objectPath = objectPaths[i];
+ let object = this._objects[objectPath];
let interfaceNames = Object.keys(object);
- for (let j = 0; i < interfaceNames.length; i++) {
- let interfaceName = interfaceNames[i];
+ for (let j = 0; j < interfaceNames.length; j++) {
+ let interfaceName = interfaceNames[j];
if (object[interfaceName])
this._removeInterface(objectPath, interfaceName);
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 651aac6..fd133cc 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -802,6 +802,8 @@ var NotificationMessage = new Lang.Class({
},
_onDestroy() {
+ this.parent();
+
if (this._updatedId)
this.notification.disconnect(this._updatedId);
this._updatedId = 0;
diff --git a/js/ui/components/automountManager.js b/js/ui/components/automountManager.js
index 2d8f3f8..a6cd857 100644
--- a/js/ui/components/automountManager.js
+++ b/js/ui/components/automountManager.js
@@ -210,6 +210,10 @@ var AutomountManager = new Lang.Class({
},
_onVolumeRemoved(monitor, volume) {
+ if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
+ Mainloop.source_remove(volume._allowAutorunExpireId);
+ delete volume._allowAutorunExpireId;
+ }
this._volumeQueue =
this._volumeQueue.filter(element => (element != volume));
},
@@ -234,8 +238,10 @@ var AutomountManager = new Lang.Class({
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false;
+ delete volume._allowAutorunExpireId;
return GLib.SOURCE_REMOVE;
});
+ volume._allowAutorunExpireId = id;
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
}
});
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 5ee2476..d75af65 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -52,6 +52,8 @@ var DashItemContainer = new Lang.Class({
this.animatingOut = false;
this.connect('destroy', () => {
+ if (this.child != null)
+ this.child.destroy();
this.label.destroy();
});
},
diff --git a/js/ui/dnd.js b/js/ui/dnd.js
index a38607c..ec1ba1d 100644
--- a/js/ui/dnd.js
+++ b/js/ui/dnd.js
@@ -396,10 +396,15 @@ var _Draggable = new Lang.Class({
return true;
},
+ _pickTargetActor() {
+ return this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
+ this._dragX, this._dragY);
+ },
+
_updateDragHover() {
this._updateHoverId = 0;
- let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
- this._dragX, this._dragY);
+ let target = this._pickTargetActor();
+
let dragEvent = {
x: this._dragX,
y: this._dragY,
@@ -407,6 +412,18 @@ var _Draggable = new Lang.Class({
source: this.actor._delegate,
targetActor: target
};
+
+ let targetActorDestroyHandlerId;
+ let handleTargetActorDestroyClosure;
+ handleTargetActorDestroyClosure = () => {
+ target = this._pickTargetActor();
+ dragEvent.targetActor = target;
+ targetActorDestroyHandlerId =
+ target.connect('destroy', handleTargetActorDestroyClosure);
+ };
+ targetActorDestroyHandlerId =
+ target.connect('destroy', handleTargetActorDestroyClosure);
+
for (let i = 0; i < dragMonitors.length; i++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
@@ -417,6 +434,7 @@ var _Draggable = new Lang.Class({
}
}
}
+ dragEvent.targetActor.disconnect(targetActorDestroyHandlerId);
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js
index 7d18d0b..07c9541 100644
--- a/js/ui/endSessionDialog.js
+++ b/js/ui/endSessionDialog.js
@@ -760,7 +760,7 @@ var EndSessionDialog = new Lang.Class({
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
- _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
+ _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateTriggered);
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index e35c01a..a7a3d20 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -76,6 +76,7 @@ function disableExtension(uuid) {
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
+ delete extension.stylesheet;
}
try {
@@ -115,13 +116,18 @@ function enableExtension(uuid) {
extensionOrder.push(uuid);
let stylesheetNames = [global.session_mode + '.css', 'stylesheet.css'];
+ let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
for (let i = 0; i < stylesheetNames.length; i++) {
- let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
- if (stylesheetFile.query_exists(null)) {
- let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
+ try {
+ let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile;
break;
+ } catch (e) {
+ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+ continue; // not an error
+ log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
+ return;
}
}
@@ -131,6 +137,10 @@ function enableExtension(uuid) {
_signals.emit('extension-state-changed', extension);
return;
} catch(e) {
+ if (extension.stylesheet) {
+ theme.unload_stylesheet(extension.stylesheet);
+ delete extension.stylesheet;
+ }
logExtensionError(uuid, e);
return;
}
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 60f2653..5389700 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -418,6 +418,11 @@ var IconGrid = new Lang.Class({
},
_animationDone() {
+ this._clonesAnimating.forEach(clone => {
+ clone.source.reactive = true;
+ clone.source.opacity = 255;
+ clone.destroy();
+ });
this._clonesAnimating = [];
this.emit('animation-done');
},
@@ -538,10 +543,6 @@ var IconGrid = new Lang.Class({
onComplete: () => {
if (isLastItem)
this._animationDone();
-
- actor.opacity = 255;
- actor.reactive = true;
- actorClone.destroy();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
@@ -562,12 +563,8 @@ var IconGrid = new Lang.Class({
scale_x: scaleX,
scale_y: scaleY,
onComplete: () => {
- if (isLastItem) {
+ if (isLastItem)
this._animationDone();
- this._restoreItemsOpacity();
- }
- actor.reactive = true;
- actorClone.destroy();
}};
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
@@ -581,12 +578,6 @@ var IconGrid = new Lang.Class({
}
},
- _restoreItemsOpacity() {
- for (let index = 0; index < this._items.length; index++) {
- this._items[index].actor.opacity = 255;
- }
- },
-
_getAllocatedChildSizeAndSpacing(child) {
let [,, natWidth, natHeight] = child.get_preferred_size();
let width = Math.min(this._getHItemSize(), natWidth);
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index 5fcdf98..4413846 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -533,17 +533,25 @@ var FocusTracker = new Lang.Class({
},
_setCurrentRect(rect) {
- let frameRect = this._currentWindow.get_frame_rect();
- rect.x -= frameRect.x;
- rect.y -= frameRect.y;
+ if (this._currentWindow) {
+ let frameRect = this._currentWindow.get_frame_rect();
+ rect.x -= frameRect.x;
+ rect.y -= frameRect.y;
+ }
this._rect = rect;
this.emit('position-changed');
},
getCurrentRect() {
- let frameRect = this._currentWindow.get_frame_rect();
- let rect = { x: this._rect.x + frameRect.x, y: this._rect.y + frameRect.y, width: this._rect.width, height: this._rect.height };
+ let rect = { x: this._rect.x, y: this._rect.y,
+ width: this._rect.width, height: this._rect.height };
+
+ if (this._currentWindow) {
+ let frameRect = this._currentWindow.get_frame_rect();
+ rect.x += frameRect.x;
+ rect.y += frameRect.y;
+ }
return rect;
}
@@ -916,9 +924,11 @@ var Keyboard = new Lang.Class({
},
_relayout() {
- if (this.actor == null)
- return;
let monitor = Main.layoutManager.keyboardMonitor;
+
+ if (this.actor == null || monitor == null)
+ return;
+
let maxHeight = monitor.height / 3;
this.actor.width = monitor.width;
this.actor.height = maxHeight;
diff --git a/js/ui/layout.js b/js/ui/layout.js
index 6f81039..e615e56 100644
--- a/js/ui/layout.js
+++ b/js/ui/layout.js
@@ -203,6 +203,7 @@ var LayoutManager = new Lang.Class({
// Set up stage hierarchy to group all UI actors under one container.
this.uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
+ this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
this.uiGroup.connect('allocate', (actor, box, flags) => {
let children = actor.get_children();
for (let i = 0; i < children.length; i++)
@@ -557,6 +558,8 @@ var LayoutManager = new Lang.Class({
},
get focusMonitor() {
+ if (this.focusIndex < 0)
+ return null;
return this.monitors[this.focusIndex];
},
diff --git a/js/ui/main.js b/js/ui/main.js
index d86cf9e..2c54bb6 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -343,6 +343,9 @@ function loadTheme() {
let theme = new St.Theme ({ application_stylesheet: _cssStylesheet,
default_stylesheet: _defaultCssStylesheet });
+ if (theme.default_stylesheet == null)
+ throw new Error("No valid stylesheet found for '%s'".format(sessionMode.stylesheetName));
+
if (previousTheme) {
let customStylesheets = previousTheme.get_custom_stylesheets();
diff --git a/js/ui/messageList.js b/js/ui/messageList.js
index aff201e..2d397c1 100644
--- a/js/ui/messageList.js
+++ b/js/ui/messageList.js
@@ -362,7 +362,8 @@ var Message = new Lang.Class({
this.setBody(body);
this._closeButton.connect('clicked', this.close.bind(this));
- this.actor.connect('notify::hover', this._sync.bind(this));
+ let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this));
+ this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId));
this.actor.connect('clicked', this._onClicked.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._sync();
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 9ce5b44..3fdaaac 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -1320,6 +1320,7 @@ var MessageTray = new Lang.Class({
this._bannerBin.y = -this._banner.actor.height;
this.actor.show();
+ Meta.disable_unredirect_for_display(global.display);
this._updateShowingNotification();
let [x, y, mods] = global.get_pointer();
@@ -1457,6 +1458,7 @@ var MessageTray = new Lang.Class({
this._pointerInNotification = false;
this._notificationRemoved = false;
+ Meta.enable_unredirect_for_display(global.display);
this._banner.actor.destroy();
this._banner = null;
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index 9f08562..dffb412 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -117,10 +117,8 @@ var FdoNotificationDaemon = new Lang.Class({
bitsPerSample, nChannels, data] = hints['image-data'];
return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
- } else if (hints['image-path']) {
- return new Gio.FileIcon({ file: Gio.File.new_for_path(hints['image-path']) });
}
- return null;
+ return this._iconForNotificationData(hints['image-path']);
},
_fallbackIconForNotificationData(hints) {
diff --git a/js/ui/osdWindow.js b/js/ui/osdWindow.js
index a739124..97e0498 100644
--- a/js/ui/osdWindow.js
+++ b/js/ui/osdWindow.js
@@ -108,15 +108,30 @@ var OsdWindow = new Lang.Class({
this._hideTimeoutId = 0;
this._reset();
- Main.layoutManager.connect('monitors-changed',
- this._relayout.bind(this));
+ this.actor.connect('destroy', this._onDestroy.bind(this));
+
+ this._monitorsChangedId =
+ Main.layoutManager.connect('monitors-changed',
+ this._relayout.bind(this));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
- themeContext.connect('notify::scale-factor',
- this._relayout.bind(this));
+ this._scaleChangedId =
+ themeContext.connect('notify::scale-factor',
+ this._relayout.bind(this));
this._relayout();
Main.uiGroup.add_child(this.actor);
},
+ _onDestroy() {
+ if (this._monitorsChangedId)
+ Main.layoutManager.disconnect(this._monitorsChangedId);
+ this._monitorsChangedId = 0;
+
+ let themeContext = St.ThemeContext.get_for_stage(global.stage);
+ if (this._scaleChangedId)
+ themeContext.disconnect(this._scaleChangedId);
+ this._scaleChangedId = 0;
+ },
+
setIcon(icon) {
this._icon.gicon = icon;
},
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 2240576..6a463c0 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -393,10 +393,8 @@ var Overview = new Lang.Class({
if (!Main.layoutManager.primaryMonitor)
return;
- let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
-
- this._coverPane.set_position(0, workArea.y);
- this._coverPane.set_size(workArea.width, workArea.height);
+ this._coverPane.set_position(0, 0);
+ this._coverPane.set_size(global.screen_width, global.screen_height);
this._updateBackgrounds();
},
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index a2905ab..1b1c9cf 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -284,6 +284,11 @@ var ThumbnailsSlider = new Lang.Class({
return child.get_theme_node().get_length('visible-width');
},
+ _onDragEnd() {
+ this.actor.sync_hover();
+ this.parent();
+ },
+
_getSlide() {
if (!this._visible)
return 0;
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 2f59324..ef14ddf 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -796,6 +796,7 @@ var Panel = new Lang.Class({
this.actor.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this.actor.connect('allocate', this._allocate.bind(this));
this.actor.connect('button-press-event', this._onButtonPress.bind(this));
+ this.actor.connect('touch-event', this._onButtonPress.bind(this));
this.actor.connect('key-press-event', this._onKeyPress.bind(this));
Main.overview.connect('showing', () => {
@@ -939,8 +940,13 @@ var Panel = new Lang.Class({
if (event.get_source() != actor)
return Clutter.EVENT_PROPAGATE;
- let button = event.get_button();
- if (button != 1)
+ let type = event.type();
+ let isPress = type == Clutter.EventType.BUTTON_PRESS;
+ if (!isPress && type != Clutter.EventType.TOUCH_BEGIN)
+ return Clutter.EVENT_PROPAGATE;
+
+ let button = isPress ? event.get_button() : -1;
+ if (isPress && button != 1)
return Clutter.EVENT_PROPAGATE;
let focusWindow = global.display.focus_window;
@@ -1079,6 +1085,7 @@ var Panel = new Lang.Class({
let windows = activeWorkspace.list_windows().filter(metaWindow => {
return metaWindow.is_on_primary_monitor() &&
metaWindow.showing_on_its_workspace() &&
+ !metaWindow.is_hidden() &&
metaWindow.get_window_type() != Meta.WindowType.DESKTOP;
});
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index 83194d7..f449d6e 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -141,8 +141,17 @@ var PopupBaseMenuItem = new Lang.Class({
},
_onKeyPressEvent(actor, event) {
- let symbol = event.get_key_symbol();
+ let state = event.get_state();
+ // if user has a modifier down (except capslock)
+ // then don't handle the key press here
+ state &= ~Clutter.ModifierType.LOCK_MASK;
+ state &= Clutter.ModifierType.MODIFIER_MASK;
+
+ if (state)
+ return Clutter.EVENT_PROPAGATE;
+
+ let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.activate(event);
return Clutter.EVENT_STOP;
diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js
index 82deab5..1b9e260 100644
--- a/js/ui/runDialog.js
+++ b/js/ui/runDialog.js
@@ -114,18 +114,16 @@ var RunDialog = new Lang.Class({
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entryText });
+ this._entryText.connect('activate', (o) => {
+ this.popModal();
+ this._run(o.get_text(),
+ Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK);
+ if (!this._commandError ||
+ !this.pushModal())
+ this.close();
+ });
this._entryText.connect('key-press-event', (o, e) => {
let symbol = e.get_key_symbol();
- if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
- this.popModal();
- this._run(o.get_text(),
- e.get_state() & Clutter.ModifierType.CONTROL_MASK);
- if (!this._commandError ||
- !this.pushModal())
- this.close();
-
- return Clutter.EVENT_STOP;
- }
if (symbol == Clutter.Tab) {
let text = o.get_text();
let prefix;
diff --git a/js/ui/search.js b/js/ui/search.js
index 1fb54b4..3966741 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -192,6 +192,7 @@ var SearchResultsBase = new Lang.Class({
},
clear() {
+ this._cancellable.cancel();
for (let resultId in this._resultDisplays)
this._resultDisplays[resultId].actor.destroy();
this._resultDisplays = {};
@@ -225,6 +226,12 @@ var SearchResultsBase = new Lang.Class({
this._cancellable.reset();
this.provider.getResultMetas(metasNeeded, metas => {
+ if (this._cancellable.is_cancelled()) {
+ if (metas.length > 0)
+ log(`Search provider ${this.provider.id} returned results after the request was canceled`);
+ callback(false);
+ return;
+ }
if (metas.length != metasNeeded.length) {
log('Wrong number of result metas returned by search provider ' + this.provider.id +
': expected ' + metasNeeded.length + ' but got ' + metas.length);
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 3dce2c9..b80566a 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -360,11 +360,14 @@ var InputSourceManager = new Lang.Class({
this._settings.connect('per-window-changed', this._sourcesPerWindowChanged.bind(this));
this._sourcesPerWindowChanged();
this._disableIBus = false;
+ this._reloading = false;
},
reload() {
+ this._reloading = true;
this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
this._inputSourcesChanged();
+ this._reloading = false;
},
_ibusReadyCallback(im, ready) {
@@ -458,7 +461,15 @@ var InputSourceManager = new Lang.Class({
},
activateInputSource(is, interactive) {
- KeyboardManager.holdKeyboard();
+ // The focus changes during holdKeyboard/releaseKeyboard may trick
+ // the client into hiding UI containing the currently focused entry.
+ // So holdKeyboard/releaseKeyboard are not called when
+ // 'set-content-type' signal is received.
+ // E.g. Focusing on a password entry in a popup in Xorg Firefox
+ // will emit 'set-content-type' signal.
+ // https://gitlab.gnome.org/GNOME/gnome-shell/issues/391
+ if (!this._reloading)
+ KeyboardManager.holdKeyboard();
this._keyboardManager.apply(is.xkbId);
// All the "xkb:..." IBus engines simply "echo" back symbols,
@@ -473,7 +484,10 @@ var InputSourceManager = new Lang.Class({
else
engine = 'xkb:us::eng';
- this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
+ if (!this._reloading)
+ this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard);
+ else
+ this._ibusManager.setEngine(engine);
this._currentInputSourceChanged(is);
if (interactive)
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index a759936..79acef2 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -419,12 +419,14 @@ var NMConnectionDevice = new Lang.Class({
this._deactivateItem.actor.visible = this._device.state > NM.DeviceState.DISCONNECTED;
if (this._activeConnection == null) {
- this._activeConnection = this._device.active_connection;
-
- if (this._activeConnection) {
- ensureActiveConnectionProps(this._activeConnection, this._client);
- let item = this._connectionItems.get(this._activeConnection.connection.get_uuid());
- item.setActiveConnection(this._activeConnection);
+ let activeConnection = this._device.active_connection;
+ if (activeConnection && activeConnection.connection) {
+ let item = this._connectionItems.get(activeConnection.connection.get_uuid());
+ if (item) {
+ this._activeConnection = activeConnection;
+ ensureActiveConnectionProps(this._activeConnection, this._client);
+ item.setActiveConnection(this._activeConnection);
+ }
}
}
diff --git a/js/ui/status/system.js b/js/ui/status/system.js
index 68a0b4b..cd6f3d8 100644
--- a/js/ui/status/system.js
+++ b/js/ui/status/system.js
@@ -58,6 +58,9 @@ var AltSwitcher = new Lang.Class({
childToShow = this._standard;
} else if (this._alternate.visible) {
childToShow = this._alternate;
+ } else {
+ this.actor.hide();
+ return;
}
let childShown = this.actor.get_child();
@@ -79,7 +82,7 @@ var AltSwitcher = new Lang.Class({
global.sync_pointer();
}
- this.actor.visible = (childToShow != null);
+ this.actor.show();
},
_onDestroy() {
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 91bc222..24fd5de 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -311,6 +311,7 @@ var ViewSelector = new Lang.Class({
},
hide() {
+ this.reset();
this._workspacesDisplay.hide();
},
@@ -459,7 +460,11 @@ var ViewSelector = new Lang.Class({
},
reset() {
- global.stage.set_key_focus(null);
+ // Don't drop the key focus on Clutter's side if anything but the
+ // overview has pushed a modal (e.g. system modals when activated using
+ // the overview).
+ if (Main.modalCount <= 1)
+ global.stage.set_key_focus(null);
this._entry.text = '';
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index 17576a0..8e7e7a6 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -627,8 +627,8 @@ var AppSwitchAction = new Lang.Class({
if (this.get_n_current_points() == 3) {
for (let i = 0; i < this.get_n_current_points(); i++) {
- [startX, startY] = this.get_press_coords(i);
- [x, y] = this.get_motion_coords(i);
+ let [startX, startY] = this.get_press_coords(i);
+ let [x, y] = this.get_motion_coords(i);
if (Math.abs(x - startX) > MOTION_THRESHOLD ||
Math.abs(y - startY) > MOTION_THRESHOLD)
@@ -1173,6 +1173,10 @@ var WindowManager = new Lang.Class({
yScale = geom.height / actor.height;
} else {
let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
+ if (!monitor) {
+ this._minimizeWindowDone();
+ return;
+ }
xDest = monitor.x;
yDest = monitor.y;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
@@ -1248,6 +1252,11 @@ var WindowManager = new Lang.Class({
geom.height / actor.height);
} else {
let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
+ if (!monitor) {
+ actor.show();
+ this._unminimizeWindowDone();
+ return;
+ }
actor.set_position(monitor.x, monitor.y);
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
actor.x += monitor.width;
diff --git a/js/ui/windowMenu.js b/js/ui/windowMenu.js
index f0e564b..d4411d0 100644
--- a/js/ui/windowMenu.js
+++ b/js/ui/windowMenu.js
@@ -128,11 +128,10 @@ var WindowMenu = new Lang.Class({
let screen = global.screen;
let nMonitors = screen.get_n_monitors();
- if (nMonitors > 1) {
+ let monitorIndex = window.get_monitor();
+ if (nMonitors > 1 && monitorIndex >= 0) {
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- let monitorIndex = window.get_monitor();
-
let dir = Meta.ScreenDirection.UP;
let upMonitorIndex =
screen.get_monitor_neighbor_index(monitorIndex, dir);
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 8b56932..2bab2f8 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -137,8 +137,10 @@ var WindowClone = new Lang.Class({
this._dragSlot = [0, 0, 0, 0];
this._stackAbove = null;
- this._windowClone._updateId = this.metaWindow.connect('size-changed',
- this._onRealWindowSizeChanged.bind(this));
+ this._windowClone._sizeChangedId = this.metaWindow.connect('size-changed',
+ this._onMetaWindowSizeChanged.bind(this));
+ this._windowClone._posChangedId = this.metaWindow.connect('position-changed',
+ this._computeBoundingBox.bind(this));
this._windowClone._destroyId =
this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything
@@ -206,8 +208,7 @@ var WindowClone = new Lang.Class({
addAttachedDialog(win) {
this._doAddAttachedDialog(win, win.get_compositor_private());
- this._computeBoundingBox();
- this.emit('size-changed');
+ this._onMetaWindowSizeChanged();
},
hasAttachedDialogs() {
@@ -216,15 +217,14 @@ var WindowClone = new Lang.Class({
_doAddAttachedDialog(metaWin, realWin) {
let clone = new Clutter.Clone({ source: realWin });
- clone._updateId = metaWin.connect('size-changed', () => {
- this._computeBoundingBox();
- this.emit('size-changed');
- });
+ clone._sizeChangedId = metaWin.connect('size-changed',
+ this._onMetaWindowSizeChanged.bind(this));
+ clone._posChangedId = metaWin.connect('position-changed',
+ this._onMetaWindowSizeChanged.bind(this));
clone._destroyId = realWin.connect('destroy', () => {
clone.destroy();
- this._computeBoundingBox();
- this.emit('size-changed');
+ this._onMetaWindowSizeChanged();
});
this.actor.add_child(clone);
},
@@ -321,12 +321,13 @@ var WindowClone = new Lang.Class({
else
realWindow = child.source;
- realWindow.meta_window.disconnect(child._updateId);
+ realWindow.meta_window.disconnect(child._sizeChangedId);
+ realWindow.meta_window.disconnect(child._posChangedId);
realWindow.disconnect(child._destroyId);
});
},
- _onRealWindowSizeChanged() {
+ _onMetaWindowSizeChanged() {
this._computeBoundingBox();
this.emit('size-changed');
},
@@ -469,7 +470,6 @@ var WindowOverlay = new Lang.Class({
this._windowAddedId = 0;
button.hide();
- title.hide();
this.title = title;
this.closeButton = button;
@@ -544,12 +544,10 @@ var WindowOverlay = new Lang.Class({
let titleX = cloneX + (cloneWidth - title.width) / 2;
let titleY = cloneY + cloneHeight - (title.height - this.borderSize) / 2;
- if (animate) {
- this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), title.width);
- } else {
- title.width = title.width;
+ if (animate)
+ this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY));
+ else
title.set_position(Math.floor(titleX), Math.floor(titleY));
- }
let borderX = cloneX - this.borderSize;
let borderY = cloneY - this.borderSize;
@@ -568,10 +566,12 @@ var WindowOverlay = new Lang.Class({
_animateOverlayActor(actor, x, y, width, height) {
let params = { x: x,
y: y,
- width: width,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad' };
+ if (width !== undefined)
+ params.width = width;
+
if (height !== undefined)
params.height = height;
@@ -1506,7 +1506,7 @@ var Workspace = new Lang.Class({
if (metaWin.is_attached_dialog()) {
let parent = metaWin.get_transient_for();
while (parent.is_attached_dialog())
- parent = metaWin.get_transient_for();
+ parent = parent.get_transient_for();
let idx = this._lookupIndex (parent);
if (idx < 0) {
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 381169e..4aafcd3 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -68,7 +68,7 @@ var WindowClone = new Lang.Class({
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
- this.clone._updateId = this.metaWindow.connect('position-changed',
+ this.clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this));
this.clone._destroyId = this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything
@@ -153,7 +153,7 @@ var WindowClone = new Lang.Class({
let clone = new Clutter.Clone({ source: realDialog });
this._updateDialogPosition(realDialog, clone);
- clone._updateId = metaDialog.connect('position-changed', dialog => {
+ clone._updateId = realDialog.connect('notify::position', dialog => {
this._updateDialogPosition(dialog, clone);
});
clone._destroyId = realDialog.connect('destroy', () => {
@@ -171,7 +171,6 @@ var WindowClone = new Lang.Class({
},
_onPositionChanged() {
- let rect = this.metaWindow.get_frame_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y);
},
@@ -179,7 +178,7 @@ var WindowClone = new Lang.Class({
this.actor.get_children().forEach(child => {
let realWindow = child.source;
- realWindow.meta_window.disconnect(child._updateId);
+ realWindow.disconnect(child._updateId);
realWindow.disconnect(child._destroyId);
});
},
@@ -417,7 +416,7 @@ var WorkspaceThumbnail = new Lang.Class({
} else if (metaWin.is_attached_dialog()) {
let parent = metaWin.get_transient_for();
while (parent.is_attached_dialog())
- parent = metaWin.get_transient_for();
+ parent = parent.get_transient_for();
let idx = this._lookupIndex (parent);
if (idx < 0) {
@@ -677,7 +676,11 @@ var ThumbnailsBox = new Lang.Class({
this._settings.connect('changed::dynamic-workspaces',
this._updateSwitcherVisibility.bind(this));
- Main.layoutManager.connect('monitors-changed', this._rebuildThumbnails.bind(this));
+ Main.layoutManager.connect('monitors-changed', () => {
+ this._destroyThumbnails();
+ if (Main.overview.visible)
+ this._createThumbnails();
+ });
},
_updateSwitcherVisibility() {
@@ -870,9 +873,6 @@ var ThumbnailsBox = new Lang.Class({
Main.overview.connect('windows-restacked',
this._syncStacking.bind(this));
- this._workareasChangedId =
- global.screen.connect('workareas-changed', this._rebuildThumbnails.bind(this));
-
this._targetScale = 0;
this._scale = 0;
this._pendingScaleUpdate = false;
@@ -902,24 +902,12 @@ var ThumbnailsBox = new Lang.Class({
this._syncStackingId = 0;
}
- if (this._workareasChangedId > 0) {
- global.screen.disconnect(this._workareasChangedId);
- this._workareasChangedId = 0;
- }
-
for (let w = 0; w < this._thumbnails.length; w++)
this._thumbnails[w].destroy();
this._thumbnails = [];
this._porthole = null;
},
- _rebuildThumbnails() {
- this._destroyThumbnails();
-
- if (Main.overview.visible)
- this._createThumbnails();
- },
-
_workspacesChanged() {
let validThumbnails =
this._thumbnails.filter(t => t.state <= ThumbnailState.NORMAL);
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 563e43d..bb7835c 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -470,6 +470,7 @@ var WorkspacesDisplay = new Lang.Class({
this._switchWorkspaceNotifyId = 0;
this._notifyOpacityId = 0;
+ this._restackedNotifyId = 0;
this._scrollEventId = 0;
this._keyPressEventId = 0;
diff --git a/po/cs.po b/po/cs.po
index 9b7aa79..50e2ff0 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -1064,7 +1064,7 @@ msgstr "Načítá se…"
#: js/ui/dateMenu.js:321
#, javascript-format
msgid "Feels like %s."
-msgstr "Pocitově jako %s."
+msgstr "Pocitová teplota %s."
#: js/ui/dateMenu.js:324
msgid "Go online for weather information"
diff --git a/src/st/st-bin.c b/src/st/st-bin.c
index f8b58da..21b3687 100644
--- a/src/st/st-bin.c
+++ b/src/st/st-bin.c
@@ -177,15 +177,15 @@ st_bin_get_preferred_height (ClutterActor *self,
}
static void
-st_bin_dispose (GObject *gobject)
+st_bin_destroy (ClutterActor *actor)
{
- StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (gobject));
+ StBinPrivate *priv = st_bin_get_instance_private (ST_BIN (actor));
if (priv->child)
clutter_actor_destroy (priv->child);
g_assert (priv->child == NULL);
- G_OBJECT_CLASS (st_bin_parent_class)->dispose (gobject);
+ CLUTTER_ACTOR_CLASS (st_bin_parent_class)->destroy (actor);
}
static void
@@ -315,11 +315,11 @@ st_bin_class_init (StBinClass *klass)
gobject_class->set_property = st_bin_set_property;
gobject_class->get_property = st_bin_get_property;
- gobject_class->dispose = st_bin_dispose;
actor_class->get_preferred_width = st_bin_get_preferred_width;
actor_class->get_preferred_height = st_bin_get_preferred_height;
actor_class->allocate = st_bin_allocate;
+ actor_class->destroy = st_bin_destroy;
widget_class->popup_menu = st_bin_popup_menu;
widget_class->navigate_focus = st_bin_navigate_focus;
diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c
index ffb7477..3acb15c 100644
--- a/src/st/st-box-layout.c
+++ b/src/st/st-box-layout.c
@@ -90,7 +90,7 @@ adjustment_value_notify_cb (StAdjustment *adjustment,
GParamSpec *pspec,
StBoxLayout *box)
{
- clutter_actor_queue_redraw (CLUTTER_ACTOR (box));
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (box));
}
static void
@@ -490,7 +490,7 @@ st_box_layout_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
StBoxLayout *self = ST_BOX_LAYOUT (actor);
- gdouble x, y;
+ gdouble x, y, lower, upper;
StBoxLayoutPrivate *priv = self->priv;
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
ClutterActorBox allocation_box;
@@ -505,13 +505,42 @@ st_box_layout_get_paint_volume (ClutterActor *actor,
* our paint volume on that. */
if (priv->hadjustment || priv->vadjustment)
{
+ gdouble width, height;
+
clutter_actor_get_allocation_box (actor, &allocation_box);
st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);
origin.x = content_box.x1 - allocation_box.x1;
origin.y = content_box.y1 - allocation_box.y2;
origin.z = 0.f;
- clutter_paint_volume_set_width (volume, content_box.x2 - content_box.x1);
- clutter_paint_volume_set_height (volume, content_box.y2 - content_box.y1);
+
+ if (priv->hadjustment)
+ {
+ g_object_get (priv->hadjustment,
+ "lower", &lower,
+ "upper", &upper,
+ NULL);
+ width = upper - lower;
+ }
+ else
+ {
+ width = content_box.x2 - content_box.x1;
+ }
+
+ if (priv->vadjustment)
+ {
+ g_object_get (priv->vadjustment,
+ "lower", &lower,
+ "upper", &upper,
+ NULL);
+ height = upper - lower;
+ }
+ else
+ {
+ height = content_box.y2 - content_box.y1;
+ }
+
+ clutter_paint_volume_set_width (volume, width);
+ clutter_paint_volume_set_height (volume, height);
}
else if (!CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->get_paint_volume (actor, volume))
return FALSE;
diff --git a/src/st/st-button.c b/src/st/st-button.c
index 8f5c492..a3a7b24 100644
--- a/src/st/st-button.c
+++ b/src/st/st-button.c
@@ -248,14 +248,17 @@ st_button_touch_event (ClutterActor *actor,
if (event->type == CLUTTER_TOUCH_BEGIN && !priv->press_sequence)
{
clutter_input_device_sequence_grab (device, sequence, actor);
- st_button_press (button, device, 0, sequence);
+ if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
+ st_button_press (button, device, 0, sequence);
return CLUTTER_EVENT_STOP;
}
else if (event->type == CLUTTER_TOUCH_END &&
priv->device == device &&
priv->press_sequence == sequence)
{
- st_button_release (button, device, mask, 0, sequence);
+ if (!clutter_event_is_pointer_emulated ((ClutterEvent*) event))
+ st_button_release (button, device, mask, 0, sequence);
+
clutter_input_device_sequence_ungrab (device, sequence);
return CLUTTER_EVENT_STOP;
}
diff --git a/src/st/st-entry.c b/src/st/st-entry.c
index 74bdcdb..f5305c5 100644
--- a/src/st/st-entry.c
+++ b/src/st/st-entry.c
@@ -906,6 +906,13 @@ st_entry_unmap (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
}
+static gboolean
+st_entry_get_paint_volume (ClutterActor *actor,
+ ClutterPaintVolume *volume)
+{
+ return clutter_paint_volume_set_from_allocation (volume, actor);
+}
+
static void
st_entry_class_init (StEntryClass *klass)
{
@@ -923,6 +930,7 @@ st_entry_class_init (StEntryClass *klass)
actor_class->allocate = st_entry_allocate;
actor_class->paint = st_entry_paint;
actor_class->unmap = st_entry_unmap;
+ actor_class->get_paint_volume = st_entry_get_paint_volume;
actor_class->key_press_event = st_entry_key_press_event;
actor_class->key_focus_in = st_entry_key_focus_in;
@@ -1287,10 +1295,10 @@ st_entry_get_input_hints (StEntry *entry)
return clutter_text_get_input_hints (CLUTTER_TEXT (priv->entry));
}
-static gboolean
-_st_entry_icon_press_cb (ClutterActor *actor,
- ClutterButtonEvent *event,
- StEntry *entry)
+static void
+_st_entry_icon_clicked_cb (ClutterClickAction *action,
+ ClutterActor *actor,
+ StEntry *entry)
{
StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
@@ -1298,8 +1306,6 @@ _st_entry_icon_press_cb (ClutterActor *actor,
g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
else
g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
-
- return FALSE;
}
static void
@@ -1309,21 +1315,24 @@ _st_entry_set_icon (StEntry *entry,
{
if (*icon)
{
- g_signal_handlers_disconnect_by_func (*icon,
- _st_entry_icon_press_cb,
- entry);
+ clutter_actor_remove_action_by_name (*icon, "entry-icon-action");
clutter_actor_remove_child (CLUTTER_ACTOR (entry), *icon);
*icon = NULL;
}
if (new_icon)
{
+ ClutterAction *action;
+
*icon = g_object_ref (new_icon);
clutter_actor_set_reactive (*icon, TRUE);
clutter_actor_add_child (CLUTTER_ACTOR (entry), *icon);
- g_signal_connect (*icon, "button-release-event",
- G_CALLBACK (_st_entry_icon_press_cb), entry);
+
+ action = clutter_click_action_new ();
+ clutter_actor_add_action_with_name (*icon, "entry-icon-action", action);
+ g_signal_connect (action, "clicked",
+ G_CALLBACK (_st_entry_icon_clicked_cb), entry);
}
clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
diff --git a/src/st/st-scroll-view.c b/src/st/st-scroll-view.c
index bb26f54..fc0db1c 100644
--- a/src/st/st-scroll-view.c
+++ b/src/st/st-scroll-view.c
@@ -304,6 +304,13 @@ st_scroll_view_pick (ClutterActor *actor,
clutter_actor_paint (priv->vscroll);
}
+static gboolean
+st_scroll_view_get_paint_volume (ClutterActor *actor,
+ ClutterPaintVolume *volume)
+{
+ return clutter_paint_volume_set_from_allocation (volume, actor);
+}
+
static double
get_scrollbar_width (StScrollView *scroll,
gfloat for_height)
@@ -793,6 +800,7 @@ st_scroll_view_class_init (StScrollViewClass *klass)
actor_class->paint = st_scroll_view_paint;
actor_class->pick = st_scroll_view_pick;
+ actor_class->get_paint_volume = st_scroll_view_get_paint_volume;
actor_class->get_preferred_width = st_scroll_view_get_preferred_width;
actor_class->get_preferred_height = st_scroll_view_get_preferred_height;
actor_class->allocate = st_scroll_view_allocate;
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index 0c794a3..6219071 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -780,13 +780,13 @@ st_texture_cache_load (StTextureCache *cache,
if (!texture)
{
texture = load (cache, key, data, error);
- if (texture)
+ if (texture && policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texture);
- else
- return NULL;
}
- cogl_object_ref (texture);
+ if (texture && policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
+ cogl_object_ref (texture);
+
return texture;
}
@@ -984,7 +984,7 @@ file_changed_cb (GFileMonitor *monitor,
char *key;
guint file_hash;
- if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
+ if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
return;
file_hash = g_file_hash (file);
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index 8942966..0637d97 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -229,9 +229,9 @@ unpremultiply (ClutterColor *color)
{
if (color->alpha != 0)
{
- color->red = (color->red * 255 + 127) / color->alpha;
- color->green = (color->green * 255 + 127) / color->alpha;
- color->blue = (color->blue * 255 + 127) / color->alpha;
+ color->red = MIN((color->red * 255 + 127) / color->alpha, 255);
+ color->green = MIN((color->green * 255 + 127) / color->alpha, 255);
+ color->blue = MIN((color->blue * 255 + 127) / color->alpha, 255);
}
}
@@ -402,7 +402,7 @@ st_theme_node_lookup_corner (StThemeNode *node,
return COGL_INVALID_HANDLE;
key = corner_to_string (&corner);
- texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_NONE, load_corner, &corner, NULL);
+ texture = st_texture_cache_load (cache, key, ST_TEXTURE_CACHE_POLICY_FOREVER, load_corner, &corner, NULL);
if (texture)
{
@@ -1414,6 +1414,32 @@ st_theme_node_load_background_image (StThemeNode *node)
return node->background_texture != COGL_INVALID_HANDLE;
}
+static gboolean
+st_theme_node_invalidate_resources_for_file (StThemeNode *node,
+ GFile *file)
+{
+ StBorderImage *border_image;
+ gboolean changed = FALSE;
+ GFile *theme_file;
+
+ theme_file = st_theme_node_get_background_image (node);
+ if ((theme_file != NULL) && g_file_equal (theme_file, file))
+ {
+ st_theme_node_invalidate_background_image (node);
+ changed = TRUE;
+ }
+
+ border_image = st_theme_node_get_border_image (node);
+ theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
+ if ((theme_file != NULL) && g_file_equal (theme_file, file))
+ {
+ st_theme_node_invalidate_border_image (node);
+ changed = TRUE;
+ }
+
+ return changed;
+}
+
static void st_theme_node_prerender_shadow (StThemeNodePaintState *state);
static void
@@ -2751,3 +2777,17 @@ st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
state->alloc_width = 0;
state->alloc_height = 0;
}
+
+gboolean
+st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
+ GFile *file)
+{
+ if (state->node != NULL &&
+ st_theme_node_invalidate_resources_for_file (state->node, file))
+ {
+ st_theme_node_paint_state_invalidate (state);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index 940b97a..7597669 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -287,6 +287,9 @@ void st_theme_node_paint_state_free (StThemeNodePaintState *state);
void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
StThemeNodePaintState *other);
void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
+gboolean st_theme_node_paint_state_invalidate_for_file (StThemeNodePaintState *state,
+ GFile *file);
+
void st_theme_node_paint_state_set_node (StThemeNodePaintState *state,
StThemeNode *node);
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index db984ac..7c39b35 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -289,44 +289,17 @@ st_widget_texture_cache_changed (StTextureCache *cache,
{
StWidget *actor = ST_WIDGET (user_data);
StWidgetPrivate *priv = st_widget_get_instance_private (actor);
- StThemeNode *node = priv->theme_node;
- StBorderImage *border_image;
gboolean changed = FALSE;
- GFile *theme_file;
-
- if (node == NULL)
- return;
-
- theme_file = st_theme_node_get_background_image (node);
- if ((theme_file != NULL) && g_file_equal (theme_file, file))
- {
- st_theme_node_invalidate_background_image (node);
- changed = TRUE;
- }
+ int i;
- border_image = st_theme_node_get_border_image (node);
- theme_file = border_image ? st_border_image_get_file (border_image) : NULL;
- if ((theme_file != NULL) && g_file_equal (theme_file, file))
+ for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
{
- st_theme_node_invalidate_border_image (node);
- changed = TRUE;
+ StThemeNodePaintState *paint_state = &priv->paint_states[i];
+ changed |= st_theme_node_paint_state_invalidate_for_file (paint_state, file);
}
- if (changed)
- {
- /* If we prerender the background / border, we need to update
- * the paint state. We should probably implement a method to
- * the theme node to determine this, but for now, just wipe
- * the entire paint state.
- *
- * Use the existing state instead of a new one because it's
- * assumed the rest of the state will stay the same.
- */
- st_theme_node_paint_state_invalidate (current_paint_state (actor));
-
- if (clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
- clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
- }
+ if (changed && clutter_actor_is_mapped (CLUTTER_ACTOR (actor)))
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
}
static void
--
ubuntu-desktop mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop