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: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3103>
This commit is contained in:
parent
1b49cc643c
commit
00a375ce9b
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -272,7 +272,7 @@ class AutorunSource extends MessageTray.Source {
|
||||
this.showNotification(this._notification);
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
get icon() {
|
||||
return this.mount.get_icon();
|
||||
}
|
||||
|
||||
|
@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user