hterm: Add 'desktop-notification-bell' option.
If true, terminal bells emitted while the terminal does not have focus
trigger web notifications (http://www.w3.org/TR/notifications/).
I've tried to make the behavior relatively unobtrusive: web
notifications respect the audio bell squelch, and are all cleared when
the terminal gets focus or if the user clicks any notification.
BUG=chromium:208710
Change-Id: Ic114e7e71a2ad5d82b13211bf93010b65c5131f3
Reviewed-on: https://chromium-review.googlesource.com/203003
Reviewed-by: Robert Ginda <rginda@chromium.org>
Tested-by: Robert Ginda <rginda@chromium.org>
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index fbfae79..1d8a01c 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -99,6 +99,15 @@
this.bellAudio_ = this.document_.createElement('audio');
this.bellAudio_.setAttribute('preload', 'auto');
+ // All terminal bell notifications that have been generated (not necessarily
+ // shown).
+ this.bellNotificationList_ = [];
+
+ // Whether we have permission to display notifications.
+ this.desktopNotificationBell_ = false;
+ //this.notificationPermission_ = (Notification &&
+ //Notification.permission === 'granted');
+
// Cursor position and attributes saved with DECSC.
this.savedOptions_ = {};
@@ -200,6 +209,21 @@
}
},
+ 'desktop-notification-bell': function(v) {
+ if (v && Notification) {
+ // We cannot rely on having notification permission by default.
+ if (Notification.permission !== 'granted') {
+ Notification.requestPermission(function(permission) {
+ terminal.desktopNotificationBell_ = (permission === 'granted');
+ });
+ } else {
+ terminal.desktopNotificationBell_ = true;
+ }
+ } else {
+ terminal.desktopNotificationBell_ = false;
+ }
+ },
+
'background-color': function(v) {
terminal.setBackgroundColor(v);
},
@@ -2049,18 +2073,27 @@
self.cursorNode_.style.backgroundColor = self.prefs_.get('cursor-color');
}, 200);
+ // bellSquelchTimeout_ affects both audio and notification bells.
+ if (this.bellSquelchTimeout_)
+ return;
+
if (this.bellAudio_.getAttribute('src')) {
- if (this.bellSquelchTimeout_)
- return;
-
this.bellAudio_.play();
-
this.bellSequelchTimeout_ = setTimeout(function() {
delete this.bellSquelchTimeout_;
}.bind(this), 500);
} else {
delete this.bellSquelchTimeout_;
}
+
+ if (this.desktopNotificationBell_ && !this.document_.hasFocus()) {
+ var n = new Notification(
+ lib.f.replaceVars(hterm.desktopNotificationTitle,
+ {'title': this.document_.title || 'hterm'}));
+ this.bellNotificationList_.push(n);
+ // TODO: Should we try to raise the window here?
+ n.onclick = function() { self.closeBellNotifications_(); };
+ }
};
/**
@@ -2675,6 +2708,8 @@
hterm.Terminal.prototype.onFocusChange_ = function(focused) {
this.cursorNode_.setAttribute('focus', focused);
this.restyleCursor_();
+ if (focused === true)
+ this.closeBellNotifications_();
};
/**
@@ -2760,3 +2795,13 @@
hterm.Terminal.prototype.setScrollbarVisible = function(state) {
this.scrollPort_.setScrollbarVisible(state);
};
+
+/**
+ * Close all web notifications created by terminal bells.
+ */
+hterm.Terminal.prototype.closeBellNotifications_ = function() {
+ this.bellNotificationList_.forEach(function(n) {
+ n.close();
+ });
+ this.bellNotificationList_.length = 0;
+};