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 ubuntu-desktop@lists.ubuntu.com https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop