Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 107 additions & 10 deletions files/usr/share/cinnamon/applets/[email protected]/applet.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const PopupMenu = imports.ui.popupMenu;
const Settings = imports.ui.settings;
const SignalManager = imports.misc.signalManager;
const Tooltips = imports.ui.tooltips;
const MessageTray = imports.ui.messageTray;
const WindowUtils = imports.misc.windowUtils;

const MAX_TEXT_LENGTH = 1000;
Expand Down Expand Up @@ -309,6 +310,27 @@ class AppMenuButton {
this._label = new St.Label();
this.actor.add_actor(this._label);

this.notificationsBadge = new St.BoxLayout({
style_class: 'grouped-window-list-notifications-badge',
important: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE,
show_on_set_parent: false,
});
this.notificationsBadgeLabel = new St.Label({
style_class: 'grouped-window-list-notifications-badge-label',
important: true,
text: ''
});
this.notificationsBadgeLabel.clutter_text.ellipsize = false;
this.notificationsBadge.add(this.notificationsBadgeLabel, {
x_align: St.Align.START,
y_align: St.Align.START,
});
this.actor.add_child(this.notificationsBadge);
this.notificationsBadge.set_text_direction(St.TextDirection.LTR);
this.notificationsBadge.show();

this.updateLabelVisible();

this._visible = true;
Expand Down Expand Up @@ -362,6 +384,9 @@ class AppMenuButton {
this.onScrollModeChanged();
this._needsAttention = false;

this.app = this._getApp();
this.appId = this.app ? this.app.get_id() : null;
this.updateNotificationsBadge();
this.setDisplayTitle();
this.onFocus();
this.setIcon();
Expand Down Expand Up @@ -507,10 +532,7 @@ class AppMenuButton {

setDisplayTitle() {
let title = this.metaWindow.get_title();
let tracker = Cinnamon.WindowTracker.get_default();
let app = tracker.get_window_app(this.metaWindow);

if (!title) title = app ? app.get_name() : '?';
if (!title) title = this.app ? this.app.get_name() : '?';

/* Sanitize the window title to prevent dodgy window titles such as
* "); DROP TABLE windows; --. Turn all whitespaces into " " because
Expand All @@ -527,6 +549,18 @@ class AppMenuButton {
this._label.set_text(title);
}

_getApp() {
const tracker = Cinnamon.WindowTracker.get_default();
let app = tracker.get_window_app(this.metaWindow);
if (!app) {
app = tracker.get_app_from_pid(this.metaWindow.get_pid());
}
if (!app) {
app = tracker.get_app_from_pid(this.metaWindow.get_client_pid());
}
return app;
}

destroy() {
if (this._flashTimer) {
Mainloop.source_remove(this._flashTimer);
Expand Down Expand Up @@ -687,7 +721,8 @@ class AppMenuButton {
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;

let childBox = new Clutter.ActorBox();
const childBox = new Clutter.ActorBox();
const notifBadgeBox = new Clutter.ActorBox();

let [minWidth, minHeight, naturalWidth, naturalHeight] = this._iconBox.get_preferred_size();

Expand Down Expand Up @@ -717,6 +752,22 @@ class AppMenuButton {
}
this._iconBox.allocate(childBox, flags);

// Set notifications badge position
const notifBadgeOffset = 3 * global.ui_scale;
const notifBadgeXCenter = this._iconBox.x + this._iconBox.width - notifBadgeOffset;
const notifBadgeYCenter = this._iconBox.y + notifBadgeOffset;
const [nLabelMinWidth, nLabelMinHeight, nLabelNaturalWidth, nLabelNaturalHeight] = this.notificationsBadgeLabel.get_preferred_size();
const notifBadgesize = Math.max(nLabelNaturalWidth, nLabelNaturalHeight);
notifBadgeBox.x2 = Math.min(notifBadgeXCenter + Math.floor(notifBadgesize / 2), box.x2);
notifBadgeBox.x1 = notifBadgeBox.x2 - notifBadgesize;
notifBadgeBox.y1 = Math.max(notifBadgeYCenter - Math.floor(notifBadgesize / 2), 0);
notifBadgeBox.y2 = notifBadgeBox.y1 + notifBadgesize;
const notifLabelPosX = Math.floor((notifBadgesize - nLabelNaturalWidth) / 2);
const notifLabelPosY = Math.floor((notifBadgesize - nLabelNaturalHeight) / 2);
this.notificationsBadgeLabel.set_anchor_point(-notifLabelPosX, -notifLabelPosY);
this.notificationsBadge.set_size(notifBadgesize, notifBadgesize);
this.notificationsBadge.allocate(notifBadgeBox, flags);

if (this.drawLabel) {
[minWidth, minHeight, naturalWidth, naturalHeight] = this._label.get_preferred_size();

Expand Down Expand Up @@ -763,13 +814,10 @@ class AppMenuButton {
}

setIcon() {
let tracker = Cinnamon.WindowTracker.get_default();
let app = tracker.get_window_app(this.metaWindow);

this.icon_size = this._applet.icon_size;

let icon = app ?
app.create_icon_texture_for_window(this.icon_size, this.metaWindow) :
let icon = this.app ?
this.app.create_icon_texture_for_window(this.icon_size, this.metaWindow) :
new St.Icon({ icon_name: 'application-default-icon',
icon_type: St.IconType.FULLCOLOR,
icon_size: this.icon_size });
Expand Down Expand Up @@ -815,6 +863,17 @@ class AppMenuButton {
return continueFlashing;
});
}

updateNotificationsBadge() {
const nCount = Main.notificationDaemon.getNotificationCountForApp(this.app);

if (nCount > 0 && this._applet.enableNotifications) {
this.notificationsBadgeLabel.text = nCount.toString();
this.notificationsBadge.show();
} else {
this.notificationsBadge.hide();
}
}
};

class AppMenuButtonRightClickMenu extends Applet.AppletPopupMenu {
Expand Down Expand Up @@ -1043,6 +1102,7 @@ class CinnamonWindowListApplet extends Applet.Applet {
this.settings.bind("window-hover", "windowHover", this._onPreviewChanged);
this.settings.bind("window-preview-show-label", "showLabel", this._onPreviewChanged);
this.settings.bind("window-preview-scale", "previewScale", this._onPreviewChanged);
this.settings.bind("enable-notifications", "enableNotifications", this._updateAllNotificationBadges);
this.settings.bind("last-window-order", "lastWindowOrder", null);

this.signals.connect(global.display, 'window-created', this._onWindowAddedAsync, this);
Expand All @@ -1052,6 +1112,7 @@ class CinnamonWindowListApplet extends Applet.Applet {
this.signals.connect(Main.panelManager, 'monitors-changed', this._updateWatchedMonitors, this);
this.signals.connect(global.window_manager, 'switch-workspace', this._refreshAllItems, this);
this.signals.connect(Cinnamon.WindowTracker.get_default(), "window-app-changed", this._onWindowAppChanged, this);
this.signals.connect(Main.messageTray, 'notify-applet-update', this._onNotificationReceived, this);

this.signals.connect(this.actor, 'style-changed', Lang.bind(this, this._updateSpacing));

Expand All @@ -1064,11 +1125,13 @@ class CinnamonWindowListApplet extends Applet.Applet {
on_applet_added_to_panel(userEnabled) {
this._updateSpacing();
this.appletEnabled = true;
MessageTray.extensionsHandlingNotifications++;
}

on_applet_removed_from_panel() {
this.signals.disconnectAllSignals();
this.settings.finalize();
MessageTray.extensionsHandlingNotifications--;
}

on_applet_instances_changed() {
Expand Down Expand Up @@ -1507,6 +1570,40 @@ class CinnamonWindowListApplet extends Applet.Applet {
this._tooltipErodeTimer = null;
}
}

_onNotificationReceived(mtray, notification) {
let appId = notification.source.app?.get_id();

if (!appId) {
return;
}

// Add notification to all appMenuButton's with appId
let notificationAdded = false;
this._windows.forEach(window => {
if (appId === window.appId) {
notificationAdded = true;
window.updateNotificationsBadge();
}
});

if (notificationAdded) {
notification.appId = appId;
notification.connect('destroy', () => this._onNotificationDestroyed(notification));
}
}

_onNotificationDestroyed(notification) {
this._windows.forEach(window => {
if (notification.appId === window.appId) {
window.updateNotificationsBadge();
}
});
}

_updateAllNotificationBadges() {
this._windows.forEach(window => window.updateNotificationsBadge());
}
}

function main(metadata, orientation, panel_height, instance_id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
},
"dependency": "window-hover=thumbnail"
},
"enable-notifications": {
"type": "switch",
"default": true,
"description": "Show notification badges"
},
"last-window-order": {
"type": "generic",
"default": ""
Expand Down
Loading