Bug 1320361 - Popup notifications don't hide when the window is minimized on Linux. r=johannh
MozReview-Commit-ID: Lu4GOmzsuBx
--- a/toolkit/modules/PopupNotifications.jsm
+++ b/toolkit/modules/PopupNotifications.jsm
@@ -882,19 +882,41 @@ PopupNotifications.prototype = {
if (checked) {
this._setNotificationUIState(notificationEl, notification.options.checkbox.checkedState);
} else {
this._setNotificationUIState(notificationEl, notification.options.checkbox.uncheckedState);
}
},
- _showPanel: function PopupNotifications_showPanel(notificationsToShow, anchorElement) {
+ /**
+ * Sets the "noautohide" mode of the notification panel while it is closed.
+ */
+ _setNoAutoHide(value) {
+ // This method can only be used while the panel is closed because the
+ // "noautohide" attribute is stored in the initialization data of the widget
+ // associated to the <panel> element. Platforms other than Linux keep track
+ // of changes made to the attribute, but on Linux this isn't currently done
+ // because the type of GTK window created for the two cases is different
+ // anyways. In practice, this means that on Linux the panel mode can only be
+ // changed while the element is not part of the layout, in other words the
+ // panel should be closed and the <panel> element should be hidden.
+ if (value) {
+ this.panel.setAttribute("noautohide", "true");
+ } else {
+ this.panel.removeAttribute("noautohide");
+ }
+
+ // Force a layout flush to update the widget initialization data on Linux.
+ this.panel.hidden = true;
+ this.panel.clientWidth; // flush
this.panel.hidden = false;
+ },
+ _showPanel: function PopupNotifications_showPanel(notificationsToShow, anchorElement) {
notificationsToShow = notificationsToShow.filter(n => {
if (anchorElement != n.anchorElement) {
return false;
}
let dismiss = this._fireCallback(n, NOTIFICATION_EVENT_SHOWING);
if (dismiss)
n.dismissed = true;
@@ -921,43 +943,37 @@ PopupNotifications.prototype = {
}
}
if (this.isPanelOpen && this._currentAnchorElement == anchorElement) {
notificationsToShow.forEach(function(n) {
this._fireCallback(n, NOTIFICATION_EVENT_SHOWN);
}, this);
- // Make sure we update the noautohide attribute on the panel, in case it changed.
- if (notificationsToShow.some(n => n.options.persistent)) {
- this.panel.setAttribute("noautohide", "true");
- } else {
- this.panel.removeAttribute("noautohide");
- }
-
// Let tests know that the panel was updated and what notifications it was
// updated with so that tests can wait for the correct notifications to be
// added.
let event = new this.window.CustomEvent("PanelUpdated",
{"detail": notificationIds});
this.panel.dispatchEvent(event);
return;
}
// If the panel is already open but we're changing anchors, we need to hide
// it first. Otherwise it can appear in the wrong spot. (_hidePanel is
// safe to call even if the panel is already hidden.)
this._hidePanel().then(() => {
this._currentAnchorElement = anchorElement;
- if (notificationsToShow.some(n => n.options.persistent)) {
- this.panel.setAttribute("noautohide", "true");
- } else {
- this.panel.removeAttribute("noautohide");
- }
+ // Update the "noautohide" attribute on the panel based on the type of
+ // notifications displayed. This attribute cannot change until the panel
+ // is closed, but this is only relevant if we use the same panel to show
+ // multiple notifications with different persistence, which rarely, if
+ // ever, happens in practice.
+ this._setNoAutoHide(notificationsToShow.some(n => n.options.persistent));
// On OS X and Linux we need a different panel arrow color for
// click-to-play plugins, so copy the popupid and use css.
this.panel.setAttribute("popupid", this.panel.firstChild.getAttribute("popupid"));
notificationsToShow.forEach(function(n) {
// Record that the notification was actually displayed on screen.
// Notifications that were opened a second time or that were originally
// shown with "options.dismissed" will be recorded in a separate bucket.