From 00a375ce9bed4fb124042be931f400be0b405f9a Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Wed, 24 Jan 2024 12:25:21 +0100 Subject: [PATCH] messageTray: Expose Source icon as GObject property As the notification redesign affects the API anyway, we can just as well use the opportunity to modernize the code. Turning the icon into a GObject property means we no longer need a custom signal for change notifications, and the icon becomes usable in bindings. Since setting an `GThemedIcon` is common this also adds a convenience property to set the icon name directly. Part-of: --- .../gnome-shell-sass/widgets/_login-lock.scss | 4 ++ js/ui/calendar.js | 3 - js/ui/components/autorunManager.js | 2 +- js/ui/components/telepathyClient.js | 6 +- js/ui/extensionSystem.js | 2 +- js/ui/messageTray.js | 72 +++++-------------- js/ui/notificationDaemon.js | 30 ++++---- js/ui/unlockDialog.js | 19 +++-- js/ui/windowAttentionHandler.js | 4 +- 9 files changed, 52 insertions(+), 90 deletions(-) diff --git a/data/theme/gnome-shell-sass/widgets/_login-lock.scss b/data/theme/gnome-shell-sass/widgets/_login-lock.scss index ca9793173..38b9fd513 100644 --- a/data/theme/gnome-shell-sass/widgets/_login-lock.scss +++ b/data/theme/gnome-shell-sass/widgets/_login-lock.scss @@ -226,6 +226,10 @@ $_gdm_dialog_width: 23em; } } +.unlock-dialog-notification-icon { + icon-size: $large_icon_size; +} + .unlock-dialog-notification-label { padding-left: $base_padding * 2; padding-right: 0; diff --git a/js/ui/calendar.js b/js/ui/calendar.js index e83e31654..fc4ebd1b9 100644 --- a/js/ui/calendar.js +++ b/js/ui/calendar.js @@ -19,8 +19,6 @@ import {loadInterfaceXML} from '../misc/fileUtils.js'; const SHOW_WEEKDATE_KEY = 'show-weekdate'; -const MESSAGE_ICON_SIZE = -1; // pick up from CSS - const NC_ = (context, str) => `${context}\u0004${str}`; function sameYear(dateA, dateB) { @@ -795,7 +793,6 @@ class NotificationMessage extends MessageList.Message { if (this.notification.gicon) { return new St.Icon({ gicon: this.notification.gicon, - icon_size: MESSAGE_ICON_SIZE, }); } else { return null; diff --git a/js/ui/components/autorunManager.js b/js/ui/components/autorunManager.js index 58c0d1fc9..9570b1219 100644 --- a/js/ui/components/autorunManager.js +++ b/js/ui/components/autorunManager.js @@ -272,7 +272,7 @@ class AutorunSource extends MessageTray.Source { this.showNotification(this._notification); } - getIcon() { + get icon() { return this.mount.get_icon(); } diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js index be55018cf..5a5aec359 100644 --- a/js/ui/components/telepathyClient.js +++ b/js/ui/components/telepathyClient.js @@ -383,7 +383,7 @@ class ChatSource extends MessageTray.Source { this._notification.appendAliasChange(oldAlias, newAlias); } - getIcon() { + get icon() { let file = this._contact.get_avatar_file(); if (file) return new Gio.FileIcon({file}); @@ -392,12 +392,12 @@ class ChatSource extends MessageTray.Source { } _updateAvatarIcon() { - this.iconUpdated(); + this.notify('icon'); if (this._notification) { this._notification.update( this._notification.title, this._notification.bannerBodyText, - {gicon: this.getIcon()}); + {gicon: this.icon}); } } diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js index ddadb384e..356c43b2d 100644 --- a/js/ui/extensionSystem.js +++ b/js/ui/extensionSystem.js @@ -833,7 +833,7 @@ class ExtensionUpdateSource extends MessageTray.Source { super._init(this._app.get_name()); } - getIcon() { + get icon() { return this._app.app_info.get_icon(); } diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index 900f2ee71..7acccc9c4 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -580,46 +580,6 @@ export const NotificationBanner = GObject.registerClass({ } }); -export const SourceActor = GObject.registerClass( -class SourceActor extends St.Widget { - _init(source, size) { - super._init(); - - this._source = source; - this._size = size; - - this.connect('destroy', - () => (this._actorDestroyed = true)); - this._actorDestroyed = false; - - let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - this._iconBin = new St.Bin({ - x_expand: true, - height: size * scaleFactor, - width: size * scaleFactor, - }); - - this.add_child(this._iconBin); - - this._source.connectObject('icon-updated', - this._updateIcon.bind(this), this); - this._updateIcon(); - } - - setIcon(icon) { - this._iconBin.child = icon; - this._iconSet = true; - } - - _updateIcon() { - if (this._actorDestroyed) - return; - - if (!this._iconSet) - this._iconBin.child = this._source.createIcon(this._size); - } -}); - export const Source = GObject.registerClass({ Properties: { 'count': GObject.ParamSpec.int( @@ -634,10 +594,17 @@ export const Source = GObject.registerClass({ 'title', 'title', 'title', GObject.ParamFlags.READWRITE, null), + 'icon': GObject.ParamSpec.object( + 'icon', 'icon', 'icon', + GObject.ParamFlags.READWRITE, + Gio.Icon), + 'icon-name': GObject.ParamSpec.string( + 'icon-name', 'icon-name', 'icon-name', + GObject.ParamFlags.READWRITE, + null), }, Signals: { 'destroy': {param_types: [GObject.TYPE_UINT]}, - 'icon-updated': {}, 'notification-added': {param_types: [Notification.$gtype]}, 'notification-show': {param_types: [Notification.$gtype]}, }, @@ -645,7 +612,7 @@ export const Source = GObject.registerClass({ _init(title, iconName) { super._init({title}); - this.iconName = iconName; + this.icon = new Gio.ThemedIcon({name: iconName}); this.notifications = []; @@ -700,18 +667,15 @@ export const Source = GObject.registerClass({ return new NotificationBanner(notification); } - // Called to create a new icon actor. - // Provides a sane default implementation, override if you need - // something more fancy. - createIcon(size) { - return new St.Icon({ - gicon: this.getIcon(), - icon_size: size, - }); + get iconName() { + if (this.gicon instanceof Gio.ThemedIcon) + return this.gicon.iconName; + else + return null; } - getIcon() { - return new Gio.ThemedIcon({name: this.iconName}); + set iconName(iconName) { + this.icon = new Gio.ThemedIcon({name: iconName}); } _onNotificationDestroy(notification) { @@ -765,10 +729,6 @@ export const Source = GObject.registerClass({ this.run_dispose(); } - iconUpdated() { - this.emit('icon-updated'); - } - // To be overridden by subclasses open() { } diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js index 8a7a59889..4e338bbe7 100644 --- a/js/ui/notificationDaemon.js +++ b/js/ui/notificationDaemon.js @@ -5,7 +5,6 @@ import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import Shell from 'gi://Shell'; -import St from 'gi://St'; import * as Config from '../misc/config.js'; import * as Main from './main.js'; @@ -347,10 +346,11 @@ class FdoNotificationDaemonSource extends MessageTray.Source { this.destroy(); } - processNotification(notification, gicon) { - if (gicon) - this._gicon = gicon; - this.iconUpdated(); + processNotification(notification, appIcon) { + if (!this.app && appIcon) { + this._appIcon = appIcon; + this.notify('icon'); + } let tracker = Shell.WindowTracker.get_default(); if (notification.resident && this.app && tracker.focus_app === this.app) @@ -409,17 +409,13 @@ class FdoNotificationDaemonSource extends MessageTray.Source { super.destroy(); } - createIcon(size) { - if (this.app) { - return this.app.create_icon_texture(size); - } else if (this._gicon) { - return new St.Icon({ - gicon: this._gicon, - icon_size: size, - }); - } else { + get icon() { + if (this.app) + return this.app.get_icon(); + else if (this._appIcon) + return this._appIcon; + else return null; - } } }); @@ -542,8 +538,8 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source { this._notificationPending = false; } - createIcon(size) { - return this._app.create_icon_texture(size); + get icon() { + return this._app.get_icon(); } _createPolicy() { diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 0e56f6e7d..8a40845de 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -32,8 +32,6 @@ const FADE_OUT_SCALE = 0.3; const BLUR_BRIGHTNESS = 0.65; const BLUR_RADIUS = 90; -const SUMMARY_ICON_SIZE = 32; - const NotificationsBox = GObject.registerClass({ Signals: {'wake-up-screen': {}}, }, class NotificationsBox extends St.BoxLayout { @@ -83,8 +81,12 @@ const NotificationsBox = GObject.registerClass({ } _makeNotificationSource(source, box) { - let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); - box.add_child(sourceActor); + let iconActor = new St.Icon({ + style_class: 'unlock-dialog-notification-icon', + fallback_icon_name: 'application-x-executable', + }); + source.bind_property('icon', iconActor, 'gicon', GObject.BindingFlags.SYNC_CREATE); + box.add_child(iconActor); let textBox = new St.BoxLayout({ x_expand: true, @@ -114,9 +116,12 @@ const NotificationsBox = GObject.registerClass({ } _makeNotificationDetailedSource(source, box) { - let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); - let sourceBin = new St.Bin({child: sourceActor}); - box.add_child(sourceBin); + let iconActor = new St.Icon({ + style_class: 'unlock-dialog-notification-icon', + fallback_icon_name: 'application-x-executable', + }); + source.bind_property('icon', iconActor, 'gicon', GObject.BindingFlags.SYNC_CREATE); + box.add_child(iconActor); let textBox = new St.BoxLayout({vertical: true}); box.add_child(textBox); diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js index 09ffeb6e5..8ba38685e 100644 --- a/js/ui/windowAttentionHandler.js +++ b/js/ui/windowAttentionHandler.js @@ -84,8 +84,8 @@ class WindowAttentionSource extends MessageTray.Source { } } - createIcon(size) { - return this._app.create_icon_texture(size); + get icon() { + return this._app.get_icon(); } destroy(params) {