2010-01-13 20:05:20 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
|
|
|
|
const Clutter = imports.gi.Clutter;
|
2010-02-22 19:23:36 +00:00
|
|
|
const Gtk = imports.gi.Gtk;
|
2010-01-13 20:05:20 +00:00
|
|
|
const Lang = imports.lang;
|
|
|
|
const Mainloop = imports.mainloop;
|
2010-09-09 20:18:07 +00:00
|
|
|
const Meta = imports.gi.Meta;
|
2010-02-01 17:10:38 +00:00
|
|
|
const Pango = imports.gi.Pango;
|
2010-01-28 17:04:26 +00:00
|
|
|
const Shell = imports.gi.Shell;
|
2010-01-13 20:05:20 +00:00
|
|
|
const Signals = imports.signals;
|
2010-01-28 17:04:26 +00:00
|
|
|
const St = imports.gi.St;
|
2010-01-13 20:05:20 +00:00
|
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
|
|
|
|
const Main = imports.ui.main;
|
2010-10-19 19:17:36 +00:00
|
|
|
const BoxPointer = imports.ui.boxpointer;
|
2010-08-18 20:01:33 +00:00
|
|
|
const Params = imports.misc.params;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
|
|
|
const ANIMATION_TIME = 0.2;
|
|
|
|
const NOTIFICATION_TIMEOUT = 4;
|
2010-01-28 18:39:00 +00:00
|
|
|
const SUMMARY_TIMEOUT = 1;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-02-25 19:42:18 +00:00
|
|
|
const HIDE_TIMEOUT = 0.2;
|
2010-08-31 19:50:18 +00:00
|
|
|
const LONGER_HIDE_TIMEOUT = 0.6;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-06-11 21:19:18 +00:00
|
|
|
const BUTTON_ICON_SIZE = 36;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-06-23 19:20:39 +00:00
|
|
|
const MAX_SOURCE_TITLE_WIDTH = 180;
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
const State = {
|
|
|
|
HIDDEN: 0,
|
|
|
|
SHOWING: 1,
|
|
|
|
SHOWN: 2,
|
|
|
|
HIDING: 3
|
2010-01-28 18:39:00 +00:00
|
|
|
};
|
|
|
|
|
2010-02-01 20:23:49 +00:00
|
|
|
function _cleanMarkup(text) {
|
2010-02-20 03:28:47 +00:00
|
|
|
// Support &, ", ', < and >, escape all other
|
|
|
|
// occurrences of '&'.
|
2010-05-13 19:46:04 +00:00
|
|
|
let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&');
|
2010-02-01 20:23:49 +00:00
|
|
|
// Support <b>, <i>, and <u>, escape anything else
|
|
|
|
// so it displays as raw markup.
|
2010-05-13 19:46:04 +00:00
|
|
|
return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, '<$1');
|
2010-02-01 20:23:49 +00:00
|
|
|
}
|
|
|
|
|
2010-02-01 17:10:38 +00:00
|
|
|
// Notification:
|
|
|
|
// @source: the notification's Source
|
|
|
|
// @title: the title
|
|
|
|
// @banner: the banner text
|
2010-08-18 20:01:33 +00:00
|
|
|
// @params: optional additional params
|
2010-02-01 17:10:38 +00:00
|
|
|
//
|
2010-08-30 20:03:08 +00:00
|
|
|
// Creates a notification. In the banner mode, the notification
|
|
|
|
// will show an icon, @title (in bold) and @banner, all on a single
|
|
|
|
// line (with @banner ellipsized if necessary).
|
2010-02-09 16:25:10 +00:00
|
|
|
//
|
2010-08-30 20:03:08 +00:00
|
|
|
// The notification will be expandable if either it has additional
|
|
|
|
// elements that were added to it or if the @banner text did not
|
|
|
|
// fit fully in the banner mode. When the notification is expanded,
|
|
|
|
// the @banner text from the top line is always removed. The complete
|
|
|
|
// @banner text is added as the first element in the content section,
|
|
|
|
// unless 'customContent' parameter with the value 'true' is specified
|
|
|
|
// in @params.
|
2010-08-05 17:09:27 +00:00
|
|
|
//
|
2010-08-30 20:03:08 +00:00
|
|
|
// Additional notification content can be added with addActor() and
|
|
|
|
// addBody() methods. The notification content is put inside a
|
2010-02-22 19:23:36 +00:00
|
|
|
// scrollview, so if it gets too tall, the notification will scroll
|
2010-08-30 20:03:08 +00:00
|
|
|
// rather than continue to grow. In addition to this main content
|
|
|
|
// area, there is also a single-row action area, which is not
|
|
|
|
// scrolled and can contain a single actor. The action area can
|
|
|
|
// be set by calling setActionArea() method. There is also a
|
|
|
|
// convenience method addButton() for adding a button to the action
|
|
|
|
// area.
|
|
|
|
//
|
|
|
|
// @params can contain values for 'customContent', 'body', 'icon',
|
|
|
|
// and 'clear' parameters.
|
|
|
|
//
|
|
|
|
// If @params contains a 'customContent' parameter with the value %true,
|
|
|
|
// then @banner will not be shown in the body of the notification when the
|
|
|
|
// notification is expanded and calls to update() will not clear the content
|
|
|
|
// unless 'clear' parameter with value %true is explicitly specified.
|
|
|
|
//
|
|
|
|
// If @params contains a 'body' parameter, then that text will be added to
|
|
|
|
// the content area (as with addBody()).
|
2010-02-09 16:25:10 +00:00
|
|
|
//
|
2010-08-30 20:03:08 +00:00
|
|
|
// By default, the icon shown is created by calling
|
|
|
|
// source.createNotificationIcon(). However, if @params contains an 'icon'
|
|
|
|
// parameter, the passed in icon will be used.
|
|
|
|
//
|
|
|
|
// If @params contains a 'clear' parameter with the value %true, then
|
|
|
|
// the content and the action area of the notification will be cleared.
|
|
|
|
// The content area is also always cleared if 'customContent' is false
|
|
|
|
// because it might contain the @banner that didn't fit in the banner mode.
|
2010-08-18 20:01:33 +00:00
|
|
|
function Notification(source, title, banner, params) {
|
|
|
|
this._init(source, title, banner, params);
|
2010-01-13 20:05:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Notification.prototype = {
|
2010-08-18 20:01:33 +00:00
|
|
|
_init: function(source, title, banner, params) {
|
2010-01-28 18:39:00 +00:00
|
|
|
this.source = source;
|
2010-04-28 19:34:27 +00:00
|
|
|
this.urgent = false;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this.expanded = false;
|
2010-08-30 20:03:08 +00:00
|
|
|
this._customContent = false;
|
|
|
|
this._bannerBodyText = null;
|
2010-08-29 05:34:27 +00:00
|
|
|
this._titleFitsInBannerMode = true;
|
2010-08-26 20:05:27 +00:00
|
|
|
this._spacing = 0;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-07-21 04:42:37 +00:00
|
|
|
this._hasFocus = false;
|
2010-07-21 05:19:25 +00:00
|
|
|
this._lockTrayOnFocusGrab = false;
|
2010-07-21 04:42:37 +00:00
|
|
|
// We use this._prevFocusedWindow and this._prevKeyFocusActor to return the
|
|
|
|
// focus where it previously belonged after a focus grab, unless the user
|
|
|
|
// has explicitly changed that.
|
|
|
|
this._prevFocusedWindow = null;
|
|
|
|
this._prevKeyFocusActor = null;
|
|
|
|
|
|
|
|
this._focusWindowChangedId = 0;
|
|
|
|
this._focusActorChangedId = 0;
|
|
|
|
this._stageInputModeChangedId = 0;
|
|
|
|
this._capturedEventId = 0;
|
2010-07-21 05:26:25 +00:00
|
|
|
this._keyPressId = 0;
|
2010-07-21 04:42:37 +00:00
|
|
|
|
2010-07-14 21:07:06 +00:00
|
|
|
source.connect('destroy', Lang.bind(this, this.destroy));
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
this.actor = new St.Table({ name: 'notification',
|
|
|
|
reactive: true });
|
2010-04-29 14:54:05 +00:00
|
|
|
this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
|
2010-06-13 14:17:35 +00:00
|
|
|
this.actor.connect('button-release-event', Lang.bind(this,
|
|
|
|
function (actor, event) {
|
|
|
|
if (!this._actionArea ||
|
|
|
|
!this._actionArea.contains(event.get_source()))
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
this.emit('clicked');
|
2010-06-13 14:17:35 +00:00
|
|
|
}));
|
|
|
|
|
2010-07-28 15:02:32 +00:00
|
|
|
// The first line should have the title, followed by the
|
|
|
|
// banner text, but ellipsized if they won't both fit. We can't
|
|
|
|
// make St.Table or St.BoxLayout do this the way we want (don't
|
|
|
|
// show banner at all if title needs to be ellipsized), so we
|
|
|
|
// use Shell.GenericContainer.
|
|
|
|
this._bannerBox = new Shell.GenericContainer();
|
|
|
|
this._bannerBox.connect('get-preferred-width', Lang.bind(this, this._bannerBoxGetPreferredWidth));
|
|
|
|
this._bannerBox.connect('get-preferred-height', Lang.bind(this, this._bannerBoxGetPreferredHeight));
|
|
|
|
this._bannerBox.connect('allocate', Lang.bind(this, this._bannerBoxAllocate));
|
|
|
|
this.actor.add(this._bannerBox, { row: 0,
|
|
|
|
col: 1,
|
|
|
|
y_expand: false,
|
|
|
|
y_fill: false });
|
|
|
|
|
|
|
|
this._titleLabel = new St.Label();
|
|
|
|
this._bannerBox.add_actor(this._titleLabel);
|
|
|
|
this._bannerLabel = new St.Label();
|
|
|
|
this._bannerBox.add_actor(this._bannerLabel);
|
|
|
|
|
2010-08-18 20:01:33 +00:00
|
|
|
this.update(title, banner, params);
|
2010-07-21 05:19:25 +00:00
|
|
|
|
|
|
|
Main.overview.connect('showing', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._toggleFocusGrabMode();
|
|
|
|
}));
|
|
|
|
Main.overview.connect('hidden', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._toggleFocusGrabMode();
|
|
|
|
}));
|
2010-02-09 16:25:10 +00:00
|
|
|
},
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-02-09 16:25:10 +00:00
|
|
|
// update:
|
|
|
|
// @title: the new title
|
|
|
|
// @banner: the new banner
|
2010-08-18 20:01:33 +00:00
|
|
|
// @params: as in the Notification constructor
|
2010-02-09 16:25:10 +00:00
|
|
|
//
|
|
|
|
// Updates the notification by regenerating its icon and updating
|
2010-08-18 20:01:33 +00:00
|
|
|
// the title/banner. If @params.clear is %true, it will also
|
|
|
|
// remove any additional actors/action buttons previously added.
|
|
|
|
update: function(title, banner, params) {
|
2010-08-30 20:03:08 +00:00
|
|
|
params = Params.parse(params, { customContent: false,
|
2010-08-18 20:01:33 +00:00
|
|
|
body: null,
|
2010-08-05 17:09:27 +00:00
|
|
|
icon: null,
|
2010-08-18 20:01:33 +00:00
|
|
|
clear: false });
|
|
|
|
|
2010-08-30 20:03:08 +00:00
|
|
|
this._customContent = params.customContent;
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
if (this._icon)
|
|
|
|
this._icon.destroy();
|
2010-08-30 20:03:08 +00:00
|
|
|
// We always clear the content area if we don't have custom
|
|
|
|
// content because it might contain the @banner that didn't
|
|
|
|
// fit in the banner mode.
|
|
|
|
if (this._scrollArea && (!this._customContent || params.clear)) {
|
2010-02-22 19:23:36 +00:00
|
|
|
this._scrollArea.destroy();
|
|
|
|
this._scrollArea = null;
|
|
|
|
this._contentArea = null;
|
2010-02-09 16:25:10 +00:00
|
|
|
}
|
2010-08-18 20:01:33 +00:00
|
|
|
if (this._actionArea && params.clear) {
|
2010-02-22 19:23:36 +00:00
|
|
|
this._actionArea.destroy();
|
|
|
|
this._actionArea = null;
|
|
|
|
this._buttonBox = null;
|
2010-02-09 16:25:10 +00:00
|
|
|
}
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (!this._scrollArea && !this._actionArea)
|
|
|
|
this.actor.remove_style_class_name('multi-line-notification');
|
2010-02-09 16:25:10 +00:00
|
|
|
|
2010-08-05 17:09:27 +00:00
|
|
|
this._icon = params.icon || this.source.createNotificationIcon();
|
2010-02-22 19:23:36 +00:00
|
|
|
this.actor.add(this._icon, { row: 0,
|
|
|
|
col: 0,
|
|
|
|
x_expand: false,
|
|
|
|
y_expand: false,
|
2010-08-29 05:34:27 +00:00
|
|
|
y_fill: false,
|
|
|
|
y_align: St.Align.START });
|
2010-02-01 17:10:38 +00:00
|
|
|
|
2010-02-20 21:08:54 +00:00
|
|
|
title = title ? _cleanMarkup(title.replace(/\n/g, ' ')) : '';
|
2010-02-09 16:20:51 +00:00
|
|
|
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
|
2010-02-01 17:10:38 +00:00
|
|
|
|
2010-08-30 20:03:08 +00:00
|
|
|
// Unless the notification has custom content, we save this._bannerBodyText
|
|
|
|
// to add it to the content of the notification if the notification is
|
|
|
|
// expandable due to other elements in its content area or due to the banner
|
|
|
|
// not fitting fully in the single-line mode.
|
|
|
|
this._bannerBodyText = this._customContent ? null : banner;
|
2010-02-09 16:25:10 +00:00
|
|
|
|
2010-02-20 21:08:54 +00:00
|
|
|
banner = banner ? _cleanMarkup(banner.replace(/\n/g, ' ')) : '';
|
2010-02-09 16:20:51 +00:00
|
|
|
this._bannerLabel.clutter_text.set_markup(banner);
|
2010-07-28 15:02:32 +00:00
|
|
|
this._bannerLabel.queue_relayout();
|
2010-04-29 14:54:05 +00:00
|
|
|
|
|
|
|
// Add the bannerBody now if we know for sure we'll need it
|
|
|
|
if (this._bannerBodyText && this._bannerBodyText.indexOf('\n') > -1)
|
|
|
|
this._addBannerBody();
|
2010-08-30 20:03:08 +00:00
|
|
|
|
|
|
|
if (params.body)
|
2010-08-18 20:01:33 +00:00
|
|
|
this.addBody(params.body);
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updated();
|
2010-02-09 16:25:10 +00:00
|
|
|
},
|
2010-02-01 17:10:38 +00:00
|
|
|
|
2010-02-09 16:25:10 +00:00
|
|
|
// addActor:
|
2010-02-22 19:23:36 +00:00
|
|
|
// @actor: actor to add to the body of the notification
|
2010-02-09 16:25:10 +00:00
|
|
|
//
|
2010-02-22 19:23:36 +00:00
|
|
|
// Appends @actor to the notification's body
|
|
|
|
addActor: function(actor) {
|
|
|
|
if (!this._scrollArea) {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this.actor.add_style_class_name('multi-line-notification');
|
2010-02-22 19:23:36 +00:00
|
|
|
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
|
|
|
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
|
|
|
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
|
|
|
vshadows: true });
|
|
|
|
this.actor.add(this._scrollArea, { row: 1,
|
|
|
|
col: 1 });
|
|
|
|
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
|
|
|
vertical: true });
|
|
|
|
this._scrollArea.add_actor(this._contentArea);
|
2010-08-30 20:03:08 +00:00
|
|
|
// If we know the notification will be expandable, we need to add
|
|
|
|
// the banner text to the body as the first element.
|
|
|
|
this._addBannerBody();
|
2010-02-01 17:10:38 +00:00
|
|
|
}
|
2010-02-01 20:23:49 +00:00
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
this._contentArea.add(actor);
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updated();
|
2010-02-01 20:41:22 +00:00
|
|
|
},
|
|
|
|
|
2010-02-09 16:25:10 +00:00
|
|
|
// addBody:
|
|
|
|
// @text: the text
|
|
|
|
//
|
|
|
|
// Adds a multi-line label containing @text to the notification.
|
2010-02-22 19:23:36 +00:00
|
|
|
//
|
|
|
|
// Return value: the newly-added label
|
|
|
|
addBody: function(text) {
|
2010-02-09 16:25:10 +00:00
|
|
|
let body = new St.Label();
|
|
|
|
body.clutter_text.line_wrap = true;
|
2010-02-12 21:10:24 +00:00
|
|
|
body.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
2010-02-09 16:25:10 +00:00
|
|
|
body.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
|
|
|
|
|
|
text = text ? _cleanMarkup(text) : '';
|
|
|
|
body.clutter_text.set_markup(text);
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
this.addActor(body);
|
|
|
|
return body;
|
2010-02-09 16:25:10 +00:00
|
|
|
},
|
|
|
|
|
2010-02-12 20:15:03 +00:00
|
|
|
_addBannerBody: function() {
|
2010-08-30 20:03:08 +00:00
|
|
|
if (this._bannerBodyText) {
|
|
|
|
let text = this._bannerBodyText;
|
|
|
|
this._bannerBodyText = null;
|
|
|
|
this.addBody(text);
|
|
|
|
}
|
2010-02-12 20:15:03 +00:00
|
|
|
},
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
// scrollTo:
|
|
|
|
// @side: St.Side.TOP or St.Side.BOTTOM
|
|
|
|
//
|
|
|
|
// Scrolls the content area (if scrollable) to the indicated edge
|
|
|
|
scrollTo: function(side) {
|
|
|
|
// Hack to force a relayout, since the caller probably
|
|
|
|
// just added or removed something to scrollArea, and
|
|
|
|
// the adjustment needs to reflect that.
|
|
|
|
global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, 0, 0);
|
|
|
|
|
|
|
|
let adjustment = this._scrollArea.vscroll.adjustment;
|
|
|
|
if (side == St.Side.TOP)
|
|
|
|
adjustment.value = adjustment.lower;
|
|
|
|
else if (side == St.Side.BOTTOM)
|
|
|
|
adjustment.value = adjustment.upper;
|
|
|
|
},
|
|
|
|
|
|
|
|
// setActionArea:
|
|
|
|
// @actor: the actor
|
|
|
|
// @props: (option) St.Table child properties
|
|
|
|
//
|
|
|
|
// Puts @actor into the action area of the notification, replacing
|
|
|
|
// the previous contents
|
|
|
|
setActionArea: function(actor, props) {
|
|
|
|
if (this._actionArea) {
|
|
|
|
this._actionArea.destroy();
|
|
|
|
this._actionArea = null;
|
|
|
|
if (this._buttonBox)
|
|
|
|
this._buttonBox = null;
|
2010-10-06 21:25:15 +00:00
|
|
|
} else {
|
|
|
|
this._addBannerBody();
|
2010-02-22 19:23:36 +00:00
|
|
|
}
|
|
|
|
this._actionArea = actor;
|
|
|
|
|
|
|
|
if (!props)
|
|
|
|
props = {};
|
|
|
|
props.row = 2;
|
|
|
|
props.col = 1;
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this.actor.add_style_class_name('multi-line-notification');
|
2010-02-22 19:23:36 +00:00
|
|
|
this.actor.add(this._actionArea, props);
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updated();
|
2010-02-22 19:23:36 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// addButton:
|
2010-02-09 16:25:10 +00:00
|
|
|
// @id: the action ID
|
|
|
|
// @label: the label for the action's button
|
|
|
|
//
|
|
|
|
// Adds a button with the given @label to the notification. All
|
|
|
|
// action buttons will appear in a single row at the bottom of
|
|
|
|
// the notification.
|
|
|
|
//
|
|
|
|
// If the button is clicked, the notification will emit the
|
|
|
|
// %action-invoked signal with @id as a parameter
|
2010-02-22 19:23:36 +00:00
|
|
|
addButton: function(id, label) {
|
|
|
|
if (!this._buttonBox) {
|
2010-02-12 20:15:03 +00:00
|
|
|
|
2010-02-09 16:25:10 +00:00
|
|
|
let box = new St.BoxLayout({ name: 'notification-actions' });
|
2010-02-22 19:23:36 +00:00
|
|
|
this.setActionArea(box, { x_expand: false,
|
|
|
|
x_fill: false,
|
|
|
|
x_align: St.Align.END });
|
|
|
|
this._buttonBox = box;
|
2010-02-01 20:41:22 +00:00
|
|
|
}
|
|
|
|
|
2010-06-11 21:19:18 +00:00
|
|
|
let button = new St.Button();
|
|
|
|
|
|
|
|
if (Gtk.IconTheme.get_default().has_icon(id)) {
|
|
|
|
button.add_style_class_name('notification-icon-button');
|
2010-09-16 15:04:51 +00:00
|
|
|
button.child = St.TextureCache.get_default().load_icon_name(id, St.IconType.SYMBOLIC, BUTTON_ICON_SIZE);
|
2010-06-11 21:19:18 +00:00
|
|
|
} else {
|
|
|
|
button.add_style_class_name('notification-button');
|
|
|
|
button.label = label;
|
|
|
|
}
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
this._buttonBox.add(button);
|
2010-02-01 20:41:22 +00:00
|
|
|
button.connect('clicked', Lang.bind(this, function() { this.emit('action-invoked', id); }));
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updated();
|
2010-02-01 17:10:38 +00:00
|
|
|
},
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-04-28 19:34:27 +00:00
|
|
|
setUrgent: function(urgent) {
|
|
|
|
this.urgent = urgent;
|
|
|
|
},
|
|
|
|
|
2010-04-29 14:54:05 +00:00
|
|
|
_styleChanged: function() {
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
this._spacing = this.actor.get_theme_node().get_length('spacing-columns');
|
2010-04-29 14:54:05 +00:00
|
|
|
},
|
|
|
|
|
2010-02-01 17:10:38 +00:00
|
|
|
_bannerBoxGetPreferredWidth: function(actor, forHeight, alloc) {
|
2010-02-09 16:20:51 +00:00
|
|
|
let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight);
|
|
|
|
let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight);
|
2010-01-28 18:39:00 +00:00
|
|
|
|
2010-02-01 17:10:38 +00:00
|
|
|
alloc.min_size = titleMin;
|
2010-04-29 14:54:05 +00:00
|
|
|
alloc.natural_size = titleNat + this._spacing + bannerNat;
|
2010-02-01 17:10:38 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) {
|
|
|
|
[alloc.min_size, alloc.natural_size] =
|
2010-02-09 16:20:51 +00:00
|
|
|
this._titleLabel.get_preferred_height(forWidth);
|
2010-02-01 17:10:38 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_bannerBoxAllocate: function(actor, box, flags) {
|
2010-02-09 16:20:51 +00:00
|
|
|
let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
|
|
|
|
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(-1);
|
|
|
|
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(-1);
|
2010-02-01 17:10:38 +00:00
|
|
|
let availWidth = box.x2 - box.x1;
|
|
|
|
|
|
|
|
let titleBox = new Clutter.ActorBox();
|
|
|
|
titleBox.x1 = titleBox.y1 = 0;
|
|
|
|
titleBox.x2 = Math.min(titleNatW, availWidth);
|
|
|
|
titleBox.y2 = titleNatH;
|
2010-02-09 16:20:51 +00:00
|
|
|
this._titleLabel.allocate(titleBox, flags);
|
2010-08-29 05:34:27 +00:00
|
|
|
this._titleFitsInBannerMode = (titleNatW <= availWidth);
|
2010-02-01 17:10:38 +00:00
|
|
|
|
2010-08-26 20:05:27 +00:00
|
|
|
let bannerFits = true;
|
2010-04-29 14:54:05 +00:00
|
|
|
if (titleBox.x2 + this._spacing > availWidth) {
|
2010-09-10 17:35:11 +00:00
|
|
|
this._bannerLabel.opacity = 0;
|
2010-08-26 20:05:27 +00:00
|
|
|
bannerFits = false;
|
2010-02-03 20:15:12 +00:00
|
|
|
} else {
|
|
|
|
let bannerBox = new Clutter.ActorBox();
|
2010-04-29 14:54:05 +00:00
|
|
|
bannerBox.x1 = titleBox.x2 + this._spacing;
|
2010-02-03 20:15:12 +00:00
|
|
|
bannerBox.y1 = 0;
|
|
|
|
bannerBox.x2 = Math.min(bannerBox.x1 + bannerNatW, availWidth);
|
|
|
|
bannerBox.y2 = titleNatH;
|
2010-08-26 20:05:27 +00:00
|
|
|
bannerFits = (bannerBox.x1 + bannerNatW <= availWidth);
|
2010-02-09 16:20:51 +00:00
|
|
|
this._bannerLabel.allocate(bannerBox, flags);
|
2010-09-10 17:35:11 +00:00
|
|
|
|
|
|
|
// Make _bannerLabel visible if the entire notification
|
|
|
|
// fits on one line, or if the notification is currently
|
|
|
|
// unexpanded and only showing one line anyway.
|
|
|
|
if (!this.expanded || (bannerFits && this.actor.row_count == 1))
|
|
|
|
this._bannerLabel.opacity = 255;
|
2010-02-09 16:25:10 +00:00
|
|
|
}
|
2010-08-26 20:05:27 +00:00
|
|
|
|
2010-08-30 20:03:08 +00:00
|
|
|
// If the banner doesn't fully fit in the banner box, we possibly need to add the
|
|
|
|
// banner to the body. We can't do that from here though since that will force a
|
|
|
|
// relayout, so we add it to the main loop.
|
|
|
|
if (!bannerFits)
|
2010-08-26 20:05:27 +00:00
|
|
|
Mainloop.idle_add(Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._addBannerBody();
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (!this._titleFitsInBannerMode)
|
|
|
|
this.actor.add_style_class_name('multi-line-notification');
|
|
|
|
this._updated();
|
2010-08-26 20:05:27 +00:00
|
|
|
return false;
|
|
|
|
}));
|
2010-02-01 17:10:38 +00:00
|
|
|
},
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
_updated: function() {
|
|
|
|
if (this.expanded)
|
|
|
|
this.expand(false);
|
|
|
|
},
|
|
|
|
|
|
|
|
expand: function(animate) {
|
|
|
|
this.expanded = true;
|
2010-08-29 05:34:27 +00:00
|
|
|
// The banner is never shown when the title did not fit, so this
|
|
|
|
// can be an if-else statement.
|
|
|
|
if (!this._titleFitsInBannerMode) {
|
|
|
|
// Remove ellipsization from the title label and make it wrap so that
|
|
|
|
// we show the full title when the notification is expanded.
|
|
|
|
this._titleLabel.clutter_text.line_wrap = true;
|
|
|
|
this._titleLabel.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
|
|
|
this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
} else if (this.actor.row_count > 1 && this._bannerLabel.opacity != 0) {
|
2010-08-29 05:34:27 +00:00
|
|
|
// We always hide the banner if the notification has additional content.
|
|
|
|
//
|
|
|
|
// We don't need to wrap the banner that doesn't fit the way we wrap the
|
|
|
|
// title that doesn't fit because we won't have a notification with
|
|
|
|
// row_count=1 that has a banner that doesn't fully fit. We'll either add
|
|
|
|
// that banner to the content of the notification in _bannerBoxAllocate()
|
|
|
|
// or the notification will have custom content.
|
|
|
|
if (animate)
|
|
|
|
Tweener.addTween(this._bannerLabel,
|
|
|
|
{ opacity: 0,
|
|
|
|
time: ANIMATION_TIME,
|
|
|
|
transition: 'easeOutQuad' });
|
|
|
|
else
|
|
|
|
this._bannerLabel.opacity = 0;
|
|
|
|
}
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this.emit('expanded');
|
2010-02-01 17:10:38 +00:00
|
|
|
},
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
collapseCompleted: function() {
|
|
|
|
this.expanded = false;
|
2010-08-29 05:34:27 +00:00
|
|
|
// Make sure we don't line wrap the title, and ellipsize it instead.
|
|
|
|
this._titleLabel.clutter_text.line_wrap = false;
|
|
|
|
this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
|
|
|
// Restore banner opacity in case the notification is shown in the
|
|
|
|
// banner mode again on update.
|
2010-08-29 04:04:33 +00:00
|
|
|
this._bannerLabel.opacity = 255;
|
2010-02-22 22:19:32 +00:00
|
|
|
},
|
|
|
|
|
2010-07-21 05:19:25 +00:00
|
|
|
grabFocus: function(lockTray) {
|
2010-07-21 04:42:37 +00:00
|
|
|
if (this._hasFocus)
|
|
|
|
return;
|
|
|
|
|
2010-07-21 05:19:25 +00:00
|
|
|
this._lockTrayOnFocusGrab = lockTray;
|
|
|
|
|
2010-07-21 04:42:37 +00:00
|
|
|
let metaDisplay = global.screen.get_display();
|
|
|
|
|
|
|
|
this._prevFocusedWindow = metaDisplay.focus_window;
|
|
|
|
this._prevKeyFocus = global.stage.get_key_focus();
|
|
|
|
|
|
|
|
// We need to use the captured event in the overview, because we don't want to change the stage input mode to
|
|
|
|
// FOCUSED there. On the other hand, using the captured event doesn't work correctly in the main view because
|
|
|
|
// it doesn't allow focusing the windows again correctly. So we are using the FOCUSED stage input mode in the
|
|
|
|
// main view.
|
|
|
|
if (Main.overview.visible) {
|
|
|
|
if (!Main.pushModal(this.actor))
|
|
|
|
return;
|
|
|
|
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
|
|
|
} else {
|
|
|
|
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
|
|
|
|
|
|
|
this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
|
|
|
|
this._stageInputModeChangedId = global.connect('notify::stage-input-mode', Lang.bind(this, this._stageInputModeChanged));
|
2010-07-21 05:26:25 +00:00
|
|
|
|
|
|
|
this._keyPressId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
2010-07-21 04:42:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// We need to listen to this signal in the overview, as well as in the main view, to make the key bindings such as
|
|
|
|
// Alt+F2 work. When a notification has key focus, which is the case with chat notifications, all captured KEY_PRESS
|
|
|
|
// events have the actor with the key focus as their source. This makes it impossible to distinguish between the chat
|
|
|
|
// window input and the key bindings based solely on the KEY_PRESS event.
|
|
|
|
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
|
|
|
|
|
|
|
|
this._hasFocus = true;
|
2010-07-21 05:19:25 +00:00
|
|
|
if (lockTray)
|
|
|
|
Main.messageTray.lock();
|
2010-07-21 04:42:37 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_focusWindowChanged: function() {
|
|
|
|
let metaDisplay = global.screen.get_display();
|
|
|
|
// this._focusWindowChanged() will be called when we call
|
|
|
|
// global.set_stage_input_mode(Shell.StageInputMode.FOCUSED) ,
|
|
|
|
// however metaDisplay.focus_window will be null in that case. We only
|
|
|
|
// want to ungrab focus if the focus has been moved to an application
|
|
|
|
// window.
|
|
|
|
if (metaDisplay.focus_window) {
|
|
|
|
this._prevFocusedWindow = null;
|
|
|
|
this.ungrabFocus();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_focusActorChanged: function() {
|
|
|
|
let focusedActor = global.stage.get_key_focus();
|
|
|
|
if (!focusedActor || !this.actor.contains(focusedActor)) {
|
|
|
|
this._prevKeyFocusActor = null;
|
|
|
|
this.ungrabFocus();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_stageInputModeChanged: function() {
|
|
|
|
let focusedActor = global.stage.get_key_focus();
|
|
|
|
// TODO: We need to set this._prevFocusedWindow to null in order to
|
|
|
|
// get the cursor in the run dialog. However, that also means it's
|
|
|
|
// set to null when the application menu is activated, which defeats
|
|
|
|
// the point of keeping the name of the previously focused application
|
|
|
|
// in the panel. It'd be good to be able to distinguish between these
|
|
|
|
// two cases.
|
|
|
|
this._prevFocusedWindow = null;
|
|
|
|
this._prevKeyFocusActor = null;
|
|
|
|
this.ungrabFocus();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onCapturedEvent: function(actor, event) {
|
|
|
|
let source = event.get_source();
|
2010-07-21 05:26:25 +00:00
|
|
|
switch (event.type()) {
|
|
|
|
case Clutter.EventType.BUTTON_PRESS:
|
|
|
|
if (!this.actor.contains(source))
|
|
|
|
this.ungrabFocus();
|
|
|
|
break;
|
|
|
|
case Clutter.EventType.KEY_PRESS:
|
|
|
|
let symbol = event.get_key_symbol();
|
|
|
|
if (symbol == Clutter.Escape) {
|
|
|
|
Main.messageTray.escapeTray();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
_onKeyPress: function(actor, event) {
|
|
|
|
let symbol = event.get_key_symbol();
|
|
|
|
if (symbol == Clutter.Escape) {
|
|
|
|
Main.messageTray.escapeTray();
|
|
|
|
return true;
|
|
|
|
}
|
2010-07-21 04:42:37 +00:00
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
ungrabFocus: function() {
|
|
|
|
if (!this._hasFocus)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let metaDisplay = global.screen.get_display();
|
|
|
|
if (this._focusWindowChangedId > 0) {
|
|
|
|
metaDisplay.disconnect(this._focusWindowChangedId);
|
|
|
|
this._focusWindowChangedId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._focusActorChangedId > 0) {
|
|
|
|
global.stage.disconnect(this._focusActorChangedId);
|
|
|
|
this._focusActorChangedId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._stageInputModeChangedId) {
|
|
|
|
global.disconnect(this._stageInputModeChangedId);
|
|
|
|
this._stageInputModeChangedId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._capturedEventId > 0) {
|
|
|
|
Main.popModal(this.actor);
|
|
|
|
global.stage.disconnect(this._capturedEventId);
|
|
|
|
this._capturedEventId = 0;
|
|
|
|
}
|
|
|
|
|
2010-07-21 05:26:25 +00:00
|
|
|
if (this._keyPressId > 0) {
|
|
|
|
global.stage.disconnect(this._keyPressId);
|
|
|
|
this._keyPressId = 0;
|
|
|
|
}
|
|
|
|
|
2010-07-21 04:42:37 +00:00
|
|
|
this._hasFocus = false;
|
|
|
|
Main.messageTray.unlock();
|
|
|
|
|
|
|
|
if (this._prevFocusedWindow) {
|
|
|
|
metaDisplay.set_input_focus_window(this._prevFocusedWindow, false, global.get_current_time());
|
|
|
|
this._prevFocusedWindow = null;
|
|
|
|
}
|
|
|
|
if (this._prevKeyFocusActor) {
|
|
|
|
global.stage.set_key_focus(this._prevKeyFocusActor);
|
|
|
|
this._prevKeyFocusActor = null;
|
|
|
|
} else {
|
|
|
|
// We don't want to keep the actor inside the notification focused.
|
|
|
|
let focusedActor = global.stage.get_key_focus();
|
|
|
|
if (focusedActor && this.actor.contains(focusedActor))
|
|
|
|
global.stage.set_key_focus(null);
|
|
|
|
}
|
2010-07-21 05:19:25 +00:00
|
|
|
},
|
2010-07-21 04:42:37 +00:00
|
|
|
|
2010-07-21 05:19:25 +00:00
|
|
|
// Because we grab focus differently in the overview
|
|
|
|
// and in the main view, we need to change how it is
|
|
|
|
// done when we move between the two.
|
|
|
|
_toggleFocusGrabMode: function() {
|
|
|
|
if (this._hasFocus) {
|
|
|
|
this.ungrabFocus();
|
|
|
|
this.grabFocus(this._lockTrayOnFocusGrab);
|
|
|
|
}
|
2010-07-21 04:42:37 +00:00
|
|
|
},
|
|
|
|
|
2010-02-22 22:19:32 +00:00
|
|
|
destroy: function() {
|
|
|
|
this.emit('destroy');
|
2010-01-13 20:05:20 +00:00
|
|
|
}
|
|
|
|
};
|
2010-02-01 20:41:22 +00:00
|
|
|
Signals.addSignalMethods(Notification.prototype);
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-08-05 17:09:27 +00:00
|
|
|
function Source(title) {
|
|
|
|
this._init(title);
|
2010-01-13 20:05:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Source.prototype = {
|
2010-08-05 17:09:27 +00:00
|
|
|
ICON_SIZE: 24,
|
|
|
|
|
|
|
|
_init: function(title) {
|
2010-06-23 19:20:39 +00:00
|
|
|
this.title = title;
|
2010-08-05 17:09:27 +00:00
|
|
|
this._iconBin = new St.Bin({ width: this.ICON_SIZE,
|
|
|
|
height: this.ICON_SIZE });
|
|
|
|
},
|
|
|
|
|
|
|
|
// Called to create a new icon actor (of size this.ICON_SIZE).
|
|
|
|
// Must be overridden by the subclass if you do not pass icons
|
|
|
|
// explicitly to the Notification() constructor.
|
|
|
|
createNotificationIcon: function() {
|
|
|
|
throw new Error('no implementation of createNotificationIcon in ' + this);
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-08-05 17:09:27 +00:00
|
|
|
// Unlike createNotificationIcon, this always returns the same actor;
|
|
|
|
// there is only one summary icon actor for a Source.
|
|
|
|
getSummaryIcon: function() {
|
|
|
|
return this._iconBin;
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-02-01 20:23:49 +00:00
|
|
|
notify: function(notification) {
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
if (this.notification) {
|
|
|
|
this.notification.disconnect(this._notificationClickedId);
|
2010-02-25 19:42:18 +00:00
|
|
|
this.notification.disconnect(this._notificationDestroyedId);
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
}
|
2010-02-25 19:42:18 +00:00
|
|
|
|
|
|
|
this.notification = notification;
|
|
|
|
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
this._notificationClickedId = notification.connect('clicked', Lang.bind(this, this._notificationClicked));
|
2010-02-25 19:42:18 +00:00
|
|
|
this._notificationDestroyedId = notification.connect('destroy', Lang.bind(this,
|
|
|
|
function () {
|
|
|
|
if (this.notification == notification) {
|
|
|
|
this.notification = null;
|
|
|
|
this._notificationDestroyedId = 0;
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
this._notificationClickedId = 0;
|
2010-02-25 19:42:18 +00:00
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
2010-02-01 20:23:49 +00:00
|
|
|
this.emit('notify', notification);
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
|
|
|
this.emit('destroy');
|
2010-08-05 17:09:27 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
//// Protected methods ////
|
|
|
|
|
|
|
|
// The subclass must call this at least once to set the summary icon.
|
|
|
|
_setSummaryIcon: function(icon) {
|
|
|
|
if (this._iconBin.child)
|
|
|
|
this._iconBin.child.destroy();
|
|
|
|
this._iconBin.child = icon;
|
MessageTray: untangle click notifications
Previously, when you clicked on a notification, it would call
this.source.clicked(), which would emit a 'clicked' signal on the
source, and then various other stuff would happen from there. This
used to make a little bit of sense, when clicking on a notification
was supposed to do the same thing as clicking on its source, but makes
less sense now, when clicking on the source itself *doesn't* call
source.clicked()...
Change it so that when you click on a notification, the notification
emits 'clicked' itself, and the source notices that and calls its
notificationClicked() method, and the various source subclasses do
what they need to do with that, and Source no longer has a clicked
method/signal.
https://bugzilla.gnome.org/show_bug.cgi?id=631042
2010-09-30 20:41:38 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Default implementation is to do nothing, but subclass can override
|
|
|
|
_notificationClicked: function(notification) {
|
2010-01-13 20:05:20 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Signals.addSignalMethods(Source.prototype);
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
function SummaryItem(source) {
|
|
|
|
this._init(source);
|
2010-06-23 19:20:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SummaryItem.prototype = {
|
2010-09-24 20:04:56 +00:00
|
|
|
_init: function(source) {
|
2010-06-23 19:20:39 +00:00
|
|
|
this.source = source;
|
|
|
|
this.actor = new St.Button({ style_class: 'summary-source-button',
|
|
|
|
reactive: true,
|
|
|
|
track_hover: true });
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
this._sourceBox = new St.BoxLayout({ style_class: 'summary-source' });
|
2010-06-23 19:20:39 +00:00
|
|
|
|
2010-08-05 17:09:27 +00:00
|
|
|
this._sourceIcon = source.getSummaryIcon();
|
2010-09-24 20:04:56 +00:00
|
|
|
this._sourceTitleBin = new St.Bin({ y_align: St.Align.MIDDLE,
|
|
|
|
x_fill: true,
|
|
|
|
clip_to_allocation: true });
|
2010-06-23 19:20:39 +00:00
|
|
|
this._sourceTitle = new St.Label({ style_class: 'source-title',
|
|
|
|
text: source.title });
|
|
|
|
this._sourceTitle.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
|
|
this._sourceTitleBin.child = this._sourceTitle;
|
2010-09-24 20:04:56 +00:00
|
|
|
this._sourceTitleBin.width = 0;
|
2010-06-23 19:20:39 +00:00
|
|
|
|
|
|
|
this._sourceBox.add_actor(this._sourceIcon);
|
2010-09-24 20:04:56 +00:00
|
|
|
this._sourceBox.add_actor(this._sourceTitleBin, { expand: true });
|
2010-06-23 19:20:39 +00:00
|
|
|
this.actor.child = this._sourceBox;
|
|
|
|
},
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
// getTitleNaturalWidth, getTitleWidth, and setTitleWidth include
|
|
|
|
// the spacing between the icon and title (which is actually
|
|
|
|
// _sourceTitle's padding-left) as part of the width.
|
2010-06-23 19:20:39 +00:00
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
getTitleNaturalWidth: function() {
|
|
|
|
let [minWidth, naturalWidth] = this._sourceTitle.get_preferred_width(-1);
|
2010-06-23 19:20:39 +00:00
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
return Math.min(naturalWidth, MAX_SOURCE_TITLE_WIDTH);
|
2010-06-23 19:20:39 +00:00
|
|
|
},
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
getTitleWidth: function() {
|
|
|
|
return this._sourceTitleBin.width;
|
2010-06-23 19:20:39 +00:00
|
|
|
},
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
setTitleWidth: function(width) {
|
|
|
|
width = Math.round(width);
|
|
|
|
if (width != this._sourceTitleBin.width)
|
|
|
|
this._sourceTitleBin.width = width;
|
2010-06-23 19:20:39 +00:00
|
|
|
},
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
setEllipsization: function(mode) {
|
|
|
|
this._sourceTitle.clutter_text.ellipsize = mode;
|
2010-06-23 19:20:39 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-13 20:05:20 +00:00
|
|
|
function MessageTray() {
|
|
|
|
this._init();
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageTray.prototype = {
|
|
|
|
_init: function() {
|
2010-03-22 00:39:49 +00:00
|
|
|
this.actor = new St.Group({ name: 'message-tray',
|
|
|
|
reactive: true,
|
|
|
|
track_hover: true });
|
2010-03-15 16:20:10 +00:00
|
|
|
this.actor.connect('notify::hover', Lang.bind(this, this._onTrayHoverChanged));
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-04-08 18:36:20 +00:00
|
|
|
this._notificationBin = new St.Bin();
|
2010-03-22 00:39:49 +00:00
|
|
|
this.actor.add_actor(this._notificationBin);
|
2010-01-28 17:04:26 +00:00
|
|
|
this._notificationBin.hide();
|
2010-01-13 20:05:20 +00:00
|
|
|
this._notificationQueue = [];
|
2010-02-01 20:23:49 +00:00
|
|
|
this._notification = null;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-03-26 19:23:53 +00:00
|
|
|
this._summaryBin = new St.Bin({ anchor_gravity: Clutter.Gravity.NORTH_EAST });
|
2010-03-22 00:39:49 +00:00
|
|
|
this.actor.add_actor(this._summaryBin);
|
2010-02-09 18:31:39 +00:00
|
|
|
this._summary = new St.BoxLayout({ name: 'summary-mode',
|
2010-03-15 16:20:10 +00:00
|
|
|
reactive: true,
|
|
|
|
track_hover: true });
|
|
|
|
this._summary.connect('notify::hover', Lang.bind(this, this._onSummaryHoverChanged));
|
|
|
|
this._summaryBin.child = this._summary;
|
2010-02-11 20:39:43 +00:00
|
|
|
this._summaryBin.opacity = 0;
|
2010-02-09 18:31:39 +00:00
|
|
|
|
2010-10-19 19:17:36 +00:00
|
|
|
this._summaryMotionId = 0;
|
|
|
|
|
|
|
|
this._summaryNotificationBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
|
|
|
|
{ reactive: true,
|
|
|
|
track_hover: true });
|
|
|
|
this._summaryNotificationBoxPointer.actor.style_class = 'summary-notification-boxpointer';
|
|
|
|
this.actor.add_actor(this._summaryNotificationBoxPointer.actor);
|
|
|
|
this._summaryNotificationBoxPointer.actor.lower_bottom();
|
|
|
|
this._summaryNotificationBoxPointer.actor.hide();
|
|
|
|
|
2010-02-25 19:42:18 +00:00
|
|
|
this._summaryNotification = null;
|
2010-06-23 19:20:39 +00:00
|
|
|
this._clickedSummaryItem = null;
|
2010-10-19 19:17:36 +00:00
|
|
|
this._clickedSummaryItemAllocationChangedId = 0;
|
2010-09-24 20:04:56 +00:00
|
|
|
this._expandedSummaryItem = null;
|
|
|
|
this._summaryItemTitleWidth = 0;
|
|
|
|
|
|
|
|
// To simplify the summary item animation code, we pretend
|
|
|
|
// that there's an invisible SummaryItem to the left of the
|
|
|
|
// leftmost real summary item, and that it's expanded when all
|
|
|
|
// of the other items are collapsed.
|
|
|
|
this._imaginarySummaryItemTitleWidth = 0;
|
2010-02-25 19:42:18 +00:00
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._trayState = State.HIDDEN;
|
2010-07-21 04:42:37 +00:00
|
|
|
this._locked = false;
|
2010-08-31 19:50:18 +00:00
|
|
|
this._useLongerTrayLeftTimeout = false;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._trayLeftTimeoutId = 0;
|
|
|
|
this._pointerInTray = false;
|
|
|
|
this._summaryState = State.HIDDEN;
|
|
|
|
this._summaryTimeoutId = 0;
|
|
|
|
this._pointerInSummary = false;
|
|
|
|
this._notificationState = State.HIDDEN;
|
|
|
|
this._notificationTimeoutId = 0;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._notificationExpandedId = 0;
|
2010-02-25 19:42:18 +00:00
|
|
|
this._summaryNotificationState = State.HIDDEN;
|
|
|
|
this._summaryNotificationTimeoutId = 0;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._summaryNotificationExpandedId = 0;
|
2010-07-21 05:19:25 +00:00
|
|
|
this._overviewVisible = Main.overview.visible;
|
2010-02-22 22:19:32 +00:00
|
|
|
this._notificationRemoved = false;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._reNotifyWithSummaryNotificationAfterHide = false;
|
2010-02-09 18:31:39 +00:00
|
|
|
|
2010-02-12 17:33:00 +00:00
|
|
|
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
|
|
|
visibleInOverview: true });
|
2010-04-28 15:03:58 +00:00
|
|
|
Main.chrome.trackActor(this._notificationBin);
|
2010-10-19 19:17:36 +00:00
|
|
|
Main.chrome.trackActor(this._summaryNotificationBoxPointer.actor);
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-06-03 15:14:58 +00:00
|
|
|
global.gdk_screen.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
|
|
|
|
|
2010-01-28 17:04:26 +00:00
|
|
|
this._setSizePosition();
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-02-19 00:42:09 +00:00
|
|
|
Main.overview.connect('showing', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._overviewVisible = true;
|
2010-07-21 05:19:25 +00:00
|
|
|
if (this._locked)
|
|
|
|
this.unlock();
|
|
|
|
else
|
|
|
|
this._updateState();
|
2010-02-19 00:42:09 +00:00
|
|
|
}));
|
|
|
|
Main.overview.connect('hiding', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._overviewVisible = false;
|
2010-07-21 05:19:25 +00:00
|
|
|
if (this._locked)
|
|
|
|
this.unlock();
|
|
|
|
else
|
|
|
|
this._updateState();
|
2010-02-19 00:42:09 +00:00
|
|
|
}));
|
2010-02-12 17:33:00 +00:00
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
this._summaryItems = [];
|
2010-09-30 21:02:16 +00:00
|
|
|
// We keep a list of new summary items that were added to the summary since the last
|
|
|
|
// time it was shown to the user. We automatically show the summary to the user if there
|
|
|
|
// are items in this list once the notifications are done showing or once an item gets
|
|
|
|
// added to the summary without a notification being shown.
|
|
|
|
this._newSummaryItems = [];
|
2010-06-23 19:20:39 +00:00
|
|
|
this._longestSummaryItem = null;
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-01-25 18:28:35 +00:00
|
|
|
_setSizePosition: function() {
|
|
|
|
let primary = global.get_primary_monitor();
|
2010-02-02 13:02:32 +00:00
|
|
|
this.actor.x = primary.x;
|
|
|
|
this.actor.y = primary.y + primary.height - 1;
|
2010-01-25 18:28:35 +00:00
|
|
|
this.actor.width = primary.width;
|
2010-04-08 18:36:20 +00:00
|
|
|
this._notificationBin.x = 0;
|
|
|
|
this._notificationBin.width = primary.width;
|
2010-01-28 17:04:26 +00:00
|
|
|
|
2010-03-26 19:23:53 +00:00
|
|
|
// These work because of their anchor_gravity
|
|
|
|
this._summaryBin.x = primary.width;
|
2010-01-25 18:28:35 +00:00
|
|
|
},
|
|
|
|
|
2010-01-13 20:05:20 +00:00
|
|
|
contains: function(source) {
|
2010-08-09 17:18:15 +00:00
|
|
|
return this._getIndexOfSummaryItemForSource(source) >= 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
_getIndexOfSummaryItemForSource: function(source) {
|
|
|
|
for (let i = 0; i < this._summaryItems.length; i++) {
|
|
|
|
if (this._summaryItems[i].source == source)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
add: function(source) {
|
|
|
|
if (this.contains(source)) {
|
2010-08-09 17:18:15 +00:00
|
|
|
log('Trying to re-add source ' + source.title);
|
2010-01-13 20:05:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
let summaryItem = new SummaryItem(source);
|
2010-06-23 19:20:39 +00:00
|
|
|
|
|
|
|
this._summary.insert_actor(summaryItem.actor, 0);
|
|
|
|
|
2010-09-24 20:04:56 +00:00
|
|
|
let titleWidth = summaryItem.getTitleNaturalWidth();
|
|
|
|
if (titleWidth > this._summaryItemTitleWidth) {
|
|
|
|
this._summaryItemTitleWidth = titleWidth;
|
|
|
|
if (!this._expandedSummaryItem)
|
|
|
|
this._imaginarySummaryItemTitleWidth = titleWidth;
|
2010-06-23 19:20:39 +00:00
|
|
|
this._longestSummaryItem = summaryItem;
|
|
|
|
}
|
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
this._summaryItems.push(summaryItem);
|
2010-09-30 21:02:16 +00:00
|
|
|
this._newSummaryItems.push(summaryItem);
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-01-28 18:12:03 +00:00
|
|
|
source.connect('notify', Lang.bind(this, this._onNotify));
|
|
|
|
|
2010-06-23 19:20:39 +00:00
|
|
|
summaryItem.actor.connect('notify::hover', Lang.bind(this,
|
2010-02-25 19:42:18 +00:00
|
|
|
function () {
|
2010-06-23 19:20:39 +00:00
|
|
|
this._onSummaryItemHoverChanged(summaryItem);
|
2010-02-25 19:42:18 +00:00
|
|
|
}));
|
2010-06-23 19:20:39 +00:00
|
|
|
|
|
|
|
summaryItem.actor.connect('clicked', Lang.bind(this,
|
2010-01-13 20:05:20 +00:00
|
|
|
function () {
|
2010-06-23 19:20:39 +00:00
|
|
|
this._onSummaryItemClicked(summaryItem);
|
2010-01-13 20:05:20 +00:00
|
|
|
}));
|
|
|
|
|
|
|
|
source.connect('destroy', Lang.bind(this,
|
|
|
|
function () {
|
2010-02-22 22:19:32 +00:00
|
|
|
this.removeSource(source);
|
2010-01-13 20:05:20 +00:00
|
|
|
}));
|
2010-09-09 20:18:07 +00:00
|
|
|
|
|
|
|
// We need to display the newly-added summary item, but if the
|
|
|
|
// caller is about to post a notification, we want to show that
|
|
|
|
// *first* and not show the summary item until after it hides.
|
|
|
|
// So postpone calling _updateState() a tiny bit.
|
|
|
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-02-22 22:19:32 +00:00
|
|
|
removeSource: function(source) {
|
2010-08-09 17:18:15 +00:00
|
|
|
let index = this._getIndexOfSummaryItemForSource(source);
|
|
|
|
if (index == -1)
|
2010-01-13 20:05:20 +00:00
|
|
|
return;
|
|
|
|
|
2010-01-28 18:39:00 +00:00
|
|
|
// remove all notifications with this source from the queue
|
|
|
|
let newNotificationQueue = [];
|
|
|
|
for (let i = 0; i < this._notificationQueue.length; i++) {
|
|
|
|
if (this._notificationQueue[i].source != source)
|
|
|
|
newNotificationQueue.push(this._notificationQueue[i]);
|
|
|
|
}
|
|
|
|
this._notificationQueue = newNotificationQueue;
|
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
this._summary.remove_actor(this._summaryItems[index].actor);
|
2010-06-23 19:20:39 +00:00
|
|
|
|
2010-09-30 21:02:16 +00:00
|
|
|
let newSummaryItemsIndex = this._newSummaryItems.indexOf(this._summaryItems[index]);
|
|
|
|
if (newSummaryItemsIndex != -1)
|
|
|
|
this._newSummaryItems.splice(newSummaryItemsIndex, 1);
|
|
|
|
|
2010-08-09 17:18:15 +00:00
|
|
|
this._summaryItems.splice(index, 1);
|
2010-06-23 19:20:39 +00:00
|
|
|
if (this._longestSummaryItem.source == source) {
|
2010-09-24 20:04:56 +00:00
|
|
|
let newTitleWidth = 0;
|
2010-06-23 19:20:39 +00:00
|
|
|
this._longestSummaryItem = null;
|
2010-08-09 17:18:15 +00:00
|
|
|
for (let i = 0; i < this._summaryItems.length; i++) {
|
|
|
|
let summaryItem = this._summaryItems[i];
|
2010-09-24 20:04:56 +00:00
|
|
|
let titleWidth = summaryItem.getTitleNaturalWidth();
|
|
|
|
if (titleWidth > newTitleWidth) {
|
|
|
|
newTitleWidth = titleWidth;
|
2010-06-23 19:20:39 +00:00
|
|
|
this._longestSummaryItem = summaryItem;
|
|
|
|
}
|
|
|
|
}
|
2010-09-24 20:04:56 +00:00
|
|
|
|
|
|
|
this._summaryItemTitleWidth = newTitleWidth;
|
|
|
|
if (!this._expandedSummaryItem)
|
|
|
|
this._imaginarySummaryItemTitleWidth = newTitleWidth;
|
2010-06-23 19:20:39 +00:00
|
|
|
}
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
|
2010-02-25 19:42:18 +00:00
|
|
|
let needUpdate = false;
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
if (this._notification && this._notification.source == source) {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(0);
|
2010-02-22 22:19:32 +00:00
|
|
|
this._notificationRemoved = true;
|
2010-02-25 19:42:18 +00:00
|
|
|
needUpdate = true;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
}
|
2010-06-23 19:20:39 +00:00
|
|
|
if (this._clickedSummaryItem && this._clickedSummaryItem.source == source) {
|
2010-10-19 19:17:36 +00:00
|
|
|
this._unsetClickedSummaryItem();
|
2010-02-25 19:42:18 +00:00
|
|
|
needUpdate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needUpdate);
|
|
|
|
this._updateState();
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-02-22 22:19:32 +00:00
|
|
|
removeNotification: function(notification) {
|
|
|
|
if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(0);
|
2010-02-22 22:19:32 +00:00
|
|
|
this._notificationRemoved = true;
|
|
|
|
this._updateState();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let index = this._notificationQueue.indexOf(notification);
|
|
|
|
if (index != -1)
|
|
|
|
this._notificationQueue.splice(index, 1);
|
|
|
|
},
|
|
|
|
|
2010-02-22 19:23:36 +00:00
|
|
|
lock: function() {
|
|
|
|
this._locked = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
unlock: function() {
|
2010-07-21 05:19:25 +00:00
|
|
|
if (!this._locked)
|
|
|
|
return;
|
2010-02-22 19:23:36 +00:00
|
|
|
this._locked = false;
|
2010-10-19 19:17:36 +00:00
|
|
|
this._unsetClickedSummaryItem();
|
2010-02-22 19:23:36 +00:00
|
|
|
this._updateState();
|
|
|
|
},
|
|
|
|
|
2010-02-01 20:23:49 +00:00
|
|
|
_onNotify: function(source, notification) {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (notification == this._summaryNotification) {
|
|
|
|
if (!this._summaryNotificationExpandedId)
|
|
|
|
// We must be in the process of hiding the summary notification.
|
|
|
|
// If the summary notification is updated while it is being
|
|
|
|
// hidden, we show the update as a new notification. However,
|
|
|
|
// we must first wait till the hide is complete and the
|
|
|
|
// notification actor is not part of the stage.
|
|
|
|
this._reNotifyWithSummaryNotificationAfterHide = true;
|
2010-04-07 19:32:47 +00:00
|
|
|
return;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
}
|
2010-04-07 19:32:47 +00:00
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (this._notification == notification) {
|
|
|
|
// If a notification that is being shown is updated, we update
|
|
|
|
// how it is shown and extend the time until it auto-hides.
|
|
|
|
// If a new notification is updated while it is being hidden,
|
|
|
|
// we stop hiding it and show it again.
|
|
|
|
this._updateShowingNotification();
|
|
|
|
} else if (this._notificationQueue.indexOf(notification) < 0) {
|
2010-02-22 22:19:32 +00:00
|
|
|
notification.connect('destroy',
|
|
|
|
Lang.bind(this, this.removeNotification));
|
2010-04-28 19:34:27 +00:00
|
|
|
|
|
|
|
if (notification.urgent)
|
|
|
|
this._notificationQueue.unshift(notification);
|
|
|
|
else
|
|
|
|
this._notificationQueue.push(notification);
|
2010-02-22 22:19:32 +00:00
|
|
|
}
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._updateState();
|
2010-01-28 18:12:03 +00:00
|
|
|
},
|
|
|
|
|
2010-06-23 19:20:39 +00:00
|
|
|
_onSummaryItemHoverChanged: function(summaryItem) {
|
2010-09-24 20:04:56 +00:00
|
|
|
// We can't just animate individual summary items as the
|
|
|
|
// pointer moves in and out of them, because if they don't
|
|
|
|
// move in sync you get weird-looking wobbling. So whenever
|
|
|
|
// there's a change, we have to re-tween the entire summary
|
|
|
|
// area.
|
|
|
|
|
|
|
|
if (summaryItem.actor.hover) {
|
|
|
|
if (summaryItem == this._expandedSummaryItem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._expandedSummaryItem = summaryItem;
|
|
|
|
} else {
|
|
|
|
if (summaryItem != this._expandedSummaryItem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._expandedSummaryItem = null;
|
|
|
|
|
|
|
|
// Turn off ellipsization while collapsing; it looks better
|
|
|
|
summaryItem.setEllipsization(Pango.EllipsizeMode.NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We tween on a "_expandedSummaryItemTitleWidth" pseudo-property
|
|
|
|
// that represents the current title width of the
|
|
|
|
// expanded/expanding item, or the width of the imaginary
|
|
|
|
// invisible item if we're collapsing everything.
|
|
|
|
Tweener.addTween(this,
|
|
|
|
{ _expandedSummaryItemTitleWidth: this._summaryItemTitleWidth,
|
|
|
|
time: ANIMATION_TIME,
|
|
|
|
transition: 'easeOutQuad',
|
|
|
|
onComplete: this._expandSummaryItemCompleted,
|
|
|
|
onCompleteScope: this });
|
|
|
|
},
|
|
|
|
|
|
|
|
get _expandedSummaryItemTitleWidth() {
|
|
|
|
if (this._expandedSummaryItem)
|
|
|
|
return this._expandedSummaryItem.getTitleWidth();
|
|
|
|
else
|
|
|
|
return this._imaginarySummaryItemTitleWidth;
|
|
|
|
},
|
|
|
|
|
|
|
|
set _expandedSummaryItemTitleWidth(expansion) {
|
|
|
|
// Expand the expanding item to its new width
|
|
|
|
if (this._expandedSummaryItem)
|
|
|
|
this._expandedSummaryItem.setTitleWidth(expansion);
|
2010-06-23 19:20:39 +00:00
|
|
|
else
|
2010-09-24 20:04:56 +00:00
|
|
|
this._imaginarySummaryItemTitleWidth = expansion;
|
|
|
|
|
|
|
|
// Figure out how much space the other items are currently
|
|
|
|
// using, and how much they need to be shrunk to keep the
|
|
|
|
// total width (including the width of the imaginary item)
|
|
|
|
// constant.
|
|
|
|
let excess = this._summaryItemTitleWidth - expansion;
|
|
|
|
let oldExcess = 0, shrinkage;
|
|
|
|
if (excess) {
|
|
|
|
for (let i = 0; i < this._summaryItems.length; i++) {
|
|
|
|
if (this._summaryItems[i] != this._expandedSummaryItem)
|
|
|
|
oldExcess += this._summaryItems[i].getTitleWidth();
|
|
|
|
}
|
|
|
|
if (this._expandedSummaryItem)
|
|
|
|
oldExcess += this._imaginarySummaryItemTitleWidth;
|
|
|
|
}
|
|
|
|
if (excess && oldExcess)
|
|
|
|
shrinkage = excess / oldExcess;
|
|
|
|
else
|
|
|
|
shrinkage = 0;
|
|
|
|
|
|
|
|
// Now shrink each one proportionately
|
|
|
|
for (let i = 0; i < this._summaryItems.length; i++) {
|
|
|
|
if (this._summaryItems[i] == this._expandedSummaryItem)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
let width = this._summaryItems[i].getTitleWidth();
|
|
|
|
this._summaryItems[i].setTitleWidth(width * shrinkage);
|
|
|
|
}
|
|
|
|
if (this._expandedSummaryItem)
|
|
|
|
this._imaginarySummaryItemTitleWidth *= shrinkage;
|
|
|
|
},
|
|
|
|
|
|
|
|
_expandSummaryItemCompleted: function() {
|
|
|
|
if (this._expandedSummaryItem)
|
|
|
|
this._expandedSummaryItem.setEllipsization(Pango.EllipsizeMode.END);
|
2010-02-25 19:42:18 +00:00
|
|
|
},
|
|
|
|
|
2010-06-23 19:20:39 +00:00
|
|
|
_onSummaryItemClicked: function(summaryItem) {
|
|
|
|
if (!this._clickedSummaryItem || this._clickedSummaryItem != summaryItem)
|
2010-06-24 12:14:27 +00:00
|
|
|
this._clickedSummaryItem = summaryItem;
|
2010-06-23 19:20:39 +00:00
|
|
|
else
|
2010-10-19 19:17:36 +00:00
|
|
|
this._unsetClickedSummaryItem();
|
2010-02-25 19:42:18 +00:00
|
|
|
|
2010-06-23 19:20:39 +00:00
|
|
|
this._updateState();
|
2010-02-25 19:42:18 +00:00
|
|
|
},
|
|
|
|
|
2010-03-15 16:20:10 +00:00
|
|
|
_onSummaryHoverChanged: function() {
|
|
|
|
this._pointerInSummary = this._summary.hover;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._updateState();
|
|
|
|
},
|
2010-01-28 18:39:00 +00:00
|
|
|
|
2010-03-15 16:20:10 +00:00
|
|
|
_onTrayHoverChanged: function() {
|
|
|
|
if (this.actor.hover) {
|
2010-08-31 19:50:18 +00:00
|
|
|
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
|
|
|
|
if (this._trayState == State.HIDDEN)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Don't do anything if this._useLongerTrayLeftTimeout is true, meaning the notification originally
|
|
|
|
// popped up under the pointer, but this._trayLeftTimeoutId is 0, meaning the pointer didn't leave
|
|
|
|
// the tray yet. We need to check for this case because sometimes _onTrayHoverChanged() gets called
|
|
|
|
// multiple times while this.actor.hover is true.
|
|
|
|
if (this._useLongerTrayLeftTimeout && !this._trayLeftTimeoutId)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._useLongerTrayLeftTimeout = false;
|
2010-03-15 16:20:10 +00:00
|
|
|
if (this._trayLeftTimeoutId) {
|
|
|
|
Mainloop.source_remove(this._trayLeftTimeoutId);
|
|
|
|
this._trayLeftTimeoutId = 0;
|
|
|
|
return;
|
|
|
|
}
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-08-31 19:50:18 +00:00
|
|
|
if (this._showNotificationMouseX >= 0) {
|
|
|
|
let actorAtShowNotificationPosition =
|
|
|
|
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY);
|
|
|
|
this._showNotificationMouseX = -1;
|
|
|
|
this._showNotificationMouseY = -1;
|
|
|
|
// Don't set this._pointerInTray to true if the pointer was initially in the area where the notification
|
|
|
|
// popped up. That way we will not be expanding notifications that happen to pop up over the pointer
|
|
|
|
// automatically. Instead, the user is able to expand the notification by mousing away from it and then
|
|
|
|
// mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer
|
|
|
|
// timeout should be used before popping down the notification.
|
|
|
|
if (this._notificationBin.contains(actorAtShowNotificationPosition)) {
|
|
|
|
this._useLongerTrayLeftTimeout = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-03-15 16:20:10 +00:00
|
|
|
this._pointerInTray = true;
|
|
|
|
this._updateState();
|
|
|
|
} else {
|
2010-08-31 19:50:18 +00:00
|
|
|
// We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it.
|
|
|
|
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
|
|
|
|
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
|
|
|
|
let timeout = this._useLongerHideTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000;
|
2010-03-15 16:20:10 +00:00
|
|
|
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
}
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
_onTrayLeftTimeout: function() {
|
2010-08-31 19:50:18 +00:00
|
|
|
this._useLongerTrayLeftTimeout = false;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._trayLeftTimeoutId = 0;
|
|
|
|
this._pointerInTray = false;
|
|
|
|
this._pointerInSummary = false;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(0);
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._updateState();
|
|
|
|
return false;
|
|
|
|
},
|
2010-01-28 18:39:00 +00:00
|
|
|
|
2010-07-21 05:26:25 +00:00
|
|
|
escapeTray: function() {
|
|
|
|
this.unlock();
|
|
|
|
this._pointerInTray = false;
|
|
|
|
this._pointerInSummary = false;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(0);
|
2010-07-21 05:26:25 +00:00
|
|
|
this._updateState();
|
|
|
|
},
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
// All of the logic for what happens when occurs here; the various
|
|
|
|
// event handlers merely update variables such as
|
2010-05-13 19:46:04 +00:00
|
|
|
// 'this._pointerInTray', 'this._summaryState', etc, and
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
// _updateState() figures out what (if anything) needs to be done
|
|
|
|
// at the present time.
|
|
|
|
_updateState: function() {
|
|
|
|
// Notifications
|
|
|
|
let notificationsPending = this._notificationQueue.length > 0;
|
2010-02-22 22:19:32 +00:00
|
|
|
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
let notificationExpanded = this._notificationBin.y < 0;
|
2010-02-22 19:23:36 +00:00
|
|
|
let notificationExpired = (this._notificationTimeoutId == 0 && !this._pointerInTray && !this._locked) || this._notificationRemoved;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
|
|
|
|
if (this._notificationState == State.HIDDEN) {
|
|
|
|
if (notificationsPending)
|
2010-01-28 18:39:00 +00:00
|
|
|
this._showNotification();
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
} else if (this._notificationState == State.SHOWN) {
|
|
|
|
if (notificationExpired)
|
2010-01-28 18:39:00 +00:00
|
|
|
this._hideNotification();
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
else if (notificationPinned && !notificationExpanded)
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._expandNotification(false);
|
2010-07-21 05:19:25 +00:00
|
|
|
else if (notificationPinned)
|
|
|
|
this._ensureNotificationFocused();
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Summary
|
2010-02-19 00:42:09 +00:00
|
|
|
let summarySummoned = this._pointerInSummary || this._overviewVisible;
|
2010-07-21 04:42:37 +00:00
|
|
|
let summaryPinned = this._summaryTimeoutId != 0 || this._pointerInTray || summarySummoned || this._locked;
|
2010-02-22 22:19:32 +00:00
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
let notificationsVisible = (this._notificationState == State.SHOWING ||
|
|
|
|
this._notificationState == State.SHOWN);
|
|
|
|
let notificationsDone = !notificationsVisible && !notificationsPending;
|
|
|
|
|
|
|
|
if (this._summaryState == State.HIDDEN) {
|
2010-09-30 21:02:16 +00:00
|
|
|
if (notificationsDone && this._newSummaryItems.length > 0)
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._showSummary(true);
|
2010-07-21 04:18:54 +00:00
|
|
|
else if (summarySummoned)
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._showSummary(false);
|
|
|
|
} else if (this._summaryState == State.SHOWN) {
|
|
|
|
if (!summaryPinned)
|
2010-01-28 18:39:00 +00:00
|
|
|
this._hideSummary();
|
|
|
|
}
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-02-25 19:42:18 +00:00
|
|
|
// Summary notification
|
2010-06-23 19:20:39 +00:00
|
|
|
let haveSummaryNotification = this._clickedSummaryItem != null;
|
2010-02-25 19:42:18 +00:00
|
|
|
let summaryNotificationIsMainNotification = (haveSummaryNotification &&
|
2010-06-23 19:20:39 +00:00
|
|
|
this._clickedSummaryItem.source.notification == this._notification);
|
2010-02-25 19:42:18 +00:00
|
|
|
let canShowSummaryNotification = this._summaryState == State.SHOWN;
|
|
|
|
let wrongSummaryNotification = (haveSummaryNotification &&
|
2010-06-23 19:20:39 +00:00
|
|
|
this._summaryNotification != this._clickedSummaryItem.source.notification);
|
2010-02-25 19:42:18 +00:00
|
|
|
|
|
|
|
if (this._summaryNotificationState == State.HIDDEN) {
|
|
|
|
if (haveSummaryNotification && !summaryNotificationIsMainNotification && canShowSummaryNotification)
|
|
|
|
this._showSummaryNotification();
|
|
|
|
} else if (this._summaryNotificationState == State.SHOWN) {
|
|
|
|
if (!haveSummaryNotification || !canShowSummaryNotification || wrongSummaryNotification)
|
|
|
|
this._hideSummaryNotification();
|
|
|
|
}
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
// Tray itself
|
|
|
|
let trayIsVisible = (this._trayState == State.SHOWING ||
|
|
|
|
this._trayState == State.SHOWN);
|
|
|
|
let trayShouldBeVisible = (!notificationsDone ||
|
|
|
|
this._summaryState == State.SHOWING ||
|
|
|
|
this._summaryState == State.SHOWN);
|
|
|
|
if (!trayIsVisible && trayShouldBeVisible)
|
|
|
|
this._showTray();
|
|
|
|
else if (trayIsVisible && !trayShouldBeVisible)
|
|
|
|
this._hideTray();
|
|
|
|
},
|
|
|
|
|
|
|
|
_tween: function(actor, statevar, value, params) {
|
|
|
|
let onComplete = params.onComplete;
|
|
|
|
let onCompleteScope = params.onCompleteScope;
|
|
|
|
let onCompleteParams = params.onCompleteParams;
|
|
|
|
|
|
|
|
params.onComplete = this._tweenComplete;
|
|
|
|
params.onCompleteScope = this;
|
|
|
|
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
|
|
|
|
|
|
|
|
Tweener.addTween(actor, params);
|
|
|
|
|
|
|
|
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
|
|
|
|
this[statevar] = valuing;
|
|
|
|
},
|
|
|
|
|
|
|
|
_tweenComplete: function(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
|
|
|
|
this[statevar] = value;
|
|
|
|
if (onComplete)
|
|
|
|
onComplete.apply(onCompleteScope, onCompleteParams);
|
|
|
|
this._updateState();
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-01-28 18:39:00 +00:00
|
|
|
_showTray: function() {
|
2010-01-13 20:05:20 +00:00
|
|
|
let primary = global.get_primary_monitor();
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this.actor, '_trayState', State.SHOWN,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
{ y: primary.y + primary.height - this.actor.height,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
});
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-01-28 18:39:00 +00:00
|
|
|
_hideTray: function() {
|
2010-01-13 20:05:20 +00:00
|
|
|
let primary = global.get_primary_monitor();
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this.actor, '_trayState', State.HIDDEN,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
{ y: primary.y + primary.height - 1,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
});
|
2010-01-13 20:05:20 +00:00
|
|
|
},
|
|
|
|
|
2010-01-28 18:39:00 +00:00
|
|
|
_showNotification: function() {
|
2010-02-01 20:23:49 +00:00
|
|
|
this._notification = this._notificationQueue.shift();
|
|
|
|
this._notificationBin.child = this._notification.actor;
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-01-28 17:04:26 +00:00
|
|
|
this._notificationBin.opacity = 0;
|
|
|
|
this._notificationBin.y = this.actor.height;
|
|
|
|
this._notificationBin.show();
|
2010-01-13 20:05:20 +00:00
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateShowingNotification();
|
2010-04-29 19:06:51 +00:00
|
|
|
|
|
|
|
let [x, y, mods] = global.get_pointer();
|
2010-08-31 19:50:18 +00:00
|
|
|
// We save the position of the mouse at the time when we started showing the notification
|
|
|
|
// in order to determine if the notification popped up under it. We make that check if
|
|
|
|
// the user starts moving the mouse and _onTrayHoverChanged() gets called. We don't
|
|
|
|
// expand the notification if it just happened to pop up under the mouse unless the user
|
|
|
|
// explicitly mouses away from it and then mouses back in.
|
|
|
|
this._showNotificationMouseX = x;
|
|
|
|
this._showNotificationMouseY = y;
|
|
|
|
// We save the y coordinate of the mouse at the time when we started showing the notification
|
|
|
|
// and then we update it in _notifiationTimeout() if the mouse is moving towards the
|
|
|
|
// notification. We don't pop down the notification if the mouse is moving towards it.
|
2010-04-29 19:06:51 +00:00
|
|
|
this._lastSeenMouseY = y;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
},
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
_updateShowingNotification: function() {
|
|
|
|
Tweener.removeTweens(this._notificationBin);
|
|
|
|
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
|
|
|
|
{ y: 0,
|
|
|
|
opacity: 255,
|
|
|
|
time: ANIMATION_TIME,
|
|
|
|
transition: 'easeOutQuad',
|
|
|
|
onComplete: this._showNotificationCompleted,
|
|
|
|
onCompleteScope: this
|
|
|
|
});
|
|
|
|
|
|
|
|
// We auto-expand urgent notifications.
|
|
|
|
// We call _expandNotification() again on the notifications that
|
|
|
|
// are expanded in case they were in the process of hiding and need
|
|
|
|
// to re-expand.
|
|
|
|
if (this._notification.urgent || this._notification.expanded)
|
|
|
|
// This will overwrite the y tween, but leave the opacity
|
|
|
|
// tween, and so the onComplete will remain as well.
|
|
|
|
this._expandNotification(true);
|
|
|
|
},
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
_showNotificationCompleted: function() {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateNotificationTimeout: function(timeout) {
|
|
|
|
if (this._notificationTimeoutId) {
|
|
|
|
Mainloop.source_remove(this._notificationTimeoutId);
|
|
|
|
this._notificationTimeoutId = 0;
|
|
|
|
}
|
|
|
|
if (timeout > 0)
|
|
|
|
this._notificationTimeoutId =
|
|
|
|
Mainloop.timeout_add(timeout,
|
|
|
|
Lang.bind(this, this._notificationTimeout));
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_notificationTimeout: function() {
|
2010-04-29 19:06:51 +00:00
|
|
|
let [x, y, mods] = global.get_pointer();
|
|
|
|
if (y > this._lastSeenMouseY + 10 && y < this.actor.y) {
|
|
|
|
// The mouse is moving towards the notification, so don't
|
|
|
|
// hide it yet. (We just create a new timeout (and destroy
|
|
|
|
// the old one) each time because the bookkeeping is
|
|
|
|
// simpler.)
|
|
|
|
this._lastSeenMouseY = y;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._updateNotificationTimeout(1000);
|
2010-04-29 19:06:51 +00:00
|
|
|
} else {
|
|
|
|
this._notificationTimeoutId = 0;
|
|
|
|
this._updateState();
|
|
|
|
}
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
return false;
|
2010-01-28 18:39:00 +00:00
|
|
|
},
|
2010-01-13 20:05:20 +00:00
|
|
|
|
2010-01-28 18:39:00 +00:00
|
|
|
_hideNotification: function() {
|
2010-07-21 05:19:25 +00:00
|
|
|
this._notification.ungrabFocus();
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (this._notificationExpandedId) {
|
|
|
|
this._notification.disconnect(this._notificationExpandedId);
|
|
|
|
this._notificationExpandedId = 0;
|
2010-02-22 19:23:36 +00:00
|
|
|
}
|
|
|
|
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this._notificationBin, '_notificationState', State.HIDDEN,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
{ y: this.actor.height,
|
|
|
|
opacity: 0,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad',
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
onComplete: this._hideNotificationCompleted,
|
|
|
|
onCompleteScope: this
|
|
|
|
});
|
2010-01-28 18:39:00 +00:00
|
|
|
},
|
2010-01-13 20:05:20 +00:00
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
_hideNotificationCompleted: function() {
|
2010-02-25 21:19:11 +00:00
|
|
|
this._notificationRemoved = false;
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._notificationBin.hide();
|
|
|
|
this._notificationBin.child = null;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._notification.collapseCompleted();
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
this._notification = null;
|
|
|
|
},
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
_expandNotification: function(autoExpanding) {
|
|
|
|
// Don't grab focus in notifications that are auto-expanded.
|
|
|
|
if (!autoExpanding)
|
|
|
|
this._notification.grabFocus(false);
|
|
|
|
|
|
|
|
if (!this._notificationExpandedId)
|
|
|
|
this._notificationExpandedId =
|
|
|
|
this._notification.connect('expanded',
|
|
|
|
Lang.bind(this, this._onNotificationExpanded));
|
|
|
|
// Don't animate changes in notifications that are auto-expanding.
|
|
|
|
this._notification.expand(!autoExpanding);
|
|
|
|
},
|
|
|
|
|
|
|
|
_onNotificationExpanded: function() {
|
|
|
|
let expandedY = this.actor.height - this._notificationBin.height;
|
|
|
|
if (this._notificationBin.y != expandedY)
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
{ y: expandedY,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
});
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
},
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
|
2010-07-21 05:19:25 +00:00
|
|
|
// We use this function to grab focus when the user moves the pointer
|
|
|
|
// to an urgent notification that was already auto-expanded.
|
|
|
|
_ensureNotificationFocused: function() {
|
|
|
|
this._notification.grabFocus(false);
|
|
|
|
},
|
|
|
|
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
_showSummary: function(withTimeout) {
|
2010-02-02 13:02:32 +00:00
|
|
|
let primary = global.get_primary_monitor();
|
2010-01-28 18:39:00 +00:00
|
|
|
this._summaryBin.opacity = 0;
|
|
|
|
this._summaryBin.y = this.actor.height;
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this._summaryBin, '_summaryState', State.SHOWN,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
{ y: 0,
|
|
|
|
opacity: 255,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad',
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
onComplete: this._showSummaryCompleted,
|
|
|
|
onCompleteScope: this,
|
|
|
|
onCompleteParams: [withTimeout]
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
_showSummaryCompleted: function(withTimeout) {
|
2010-09-30 21:02:16 +00:00
|
|
|
this._newSummaryItems = [];
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
|
|
|
|
if (withTimeout) {
|
|
|
|
this._summaryTimeoutId =
|
|
|
|
Mainloop.timeout_add(SUMMARY_TIMEOUT * 1000,
|
|
|
|
Lang.bind(this, this._summaryTimeout));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_summaryTimeout: function() {
|
|
|
|
this._summaryTimeoutId = 0;
|
|
|
|
this._updateState();
|
|
|
|
return false;
|
2010-01-28 18:39:00 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_hideSummary: function() {
|
2010-05-13 19:46:04 +00:00
|
|
|
this._tween(this._summaryBin, '_summaryState', State.HIDDEN,
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
{ opacity: 0,
|
|
|
|
time: ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
[MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.
By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.
Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.
https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-11 20:31:12 +00:00
|
|
|
});
|
2010-09-30 21:02:16 +00:00
|
|
|
this._newSummaryItems = [];
|
2010-02-25 19:42:18 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_showSummaryNotification: function() {
|
2010-06-23 19:20:39 +00:00
|
|
|
this._summaryNotification = this._clickedSummaryItem.source.notification;
|
2010-02-25 19:42:18 +00:00
|
|
|
|
|
|
|
let index = this._notificationQueue.indexOf(this._summaryNotification);
|
|
|
|
if (index != -1)
|
|
|
|
this._notificationQueue.splice(index, 1);
|
|
|
|
|
2010-10-19 19:17:36 +00:00
|
|
|
this._summaryNotificationBoxPointer.bin.child = this._summaryNotification.actor;
|
2010-07-21 05:19:25 +00:00
|
|
|
this._summaryNotification.grabFocus(true);
|
2010-02-25 19:42:18 +00:00
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (!this._summaryNotificationExpandedId)
|
|
|
|
this._summaryNotificationExpandedId = this._summaryNotification.connect('expanded', Lang.bind(this, this._onSummaryNotificationExpanded));
|
|
|
|
this._summaryNotification.expand(false);
|
2010-10-19 19:17:36 +00:00
|
|
|
|
|
|
|
this._clickedSummaryItemAllocationChangedId =
|
|
|
|
this._clickedSummaryItem.actor.connect('allocation-changed',
|
|
|
|
Lang.bind(this, this._adjustNotificationBoxPointerPosition));
|
|
|
|
// _clickedSummaryItem.actor can change absolute postiion without changing allocation
|
|
|
|
this._summaryMotionId = this._summary.connect('allocation-changed',
|
|
|
|
Lang.bind(this, this._adjustNotificationBoxPointerPosition));
|
|
|
|
|
|
|
|
this._summaryNotificationBoxPointer.actor.opacity = 0;
|
|
|
|
this._summaryNotificationBoxPointer.actor.show();
|
|
|
|
this._adjustNotificationBoxPointerPosition();
|
|
|
|
|
|
|
|
this._summaryNotificationState = State.SHOWNING;
|
|
|
|
this._summaryNotificationBoxPointer.animateAppear(Lang.bind(this, function() {
|
|
|
|
this._summaryNotificationState = State.SHOWN;
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
|
|
|
_adjustNotificationBoxPointerPosition: function() {
|
|
|
|
// The position of the arrow origin should be the same as center of this._clickedSummaryItem.actor
|
|
|
|
if (!this._clickedSummaryItem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._summaryNotificationBoxPointer.setPosition(this._clickedSummaryItem.actor, 0, St.Align.MIDDLE);
|
|
|
|
},
|
|
|
|
|
|
|
|
_unsetClickedSummaryItem: function() {
|
|
|
|
if (this._clickedSummaryItemAllocationChangedId) {
|
|
|
|
this._clickedSummaryItem.actor.disconnect(this._clickedSummaryItemAllocationChangedId);
|
|
|
|
this._summary.disconnect(this._summaryMotionId);
|
|
|
|
this._clickedSummaryItemAllocationChangedId = 0;
|
|
|
|
this._summaryMotionId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._clickedSummaryItem = null;
|
2010-04-07 16:53:52 +00:00
|
|
|
},
|
|
|
|
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
_onSummaryNotificationExpanded: function() {
|
2010-10-19 19:17:36 +00:00
|
|
|
this._adjustNotificationBoxPointerPosition();
|
2010-02-25 19:42:18 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_hideSummaryNotification: function() {
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (this._summaryNotificationExpandedId) {
|
|
|
|
this._summaryNotification.disconnect(this._summaryNotificationExpandedId);
|
|
|
|
this._summaryNotificationExpandedId = 0;
|
|
|
|
}
|
2010-06-23 19:20:39 +00:00
|
|
|
// Unset this._clickedSummaryItem if we are no longer showing the summary
|
|
|
|
if (this._summaryState != State.SHOWN)
|
2010-10-19 19:17:36 +00:00
|
|
|
this._unsetClickedSummaryItem();
|
2010-02-25 19:42:18 +00:00
|
|
|
|
2010-10-19 19:17:36 +00:00
|
|
|
this._summaryNotification.ungrabFocus();
|
|
|
|
this._summaryNotificationState = State.HIDING;
|
|
|
|
this._summaryNotificationBoxPointer.animateDisappear(Lang.bind(this, this._hideSummaryNotificationCompleted));
|
2010-02-25 19:42:18 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_hideSummaryNotificationCompleted: function() {
|
2010-10-19 19:17:36 +00:00
|
|
|
this._summaryNotificationState = State.HIDDEN;
|
|
|
|
this._summaryNotificationBoxPointer.bin.child = null;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
this._summaryNotification.collapseCompleted();
|
|
|
|
let summaryNotification = this._summaryNotification;
|
2010-02-25 19:42:18 +00:00
|
|
|
this._summaryNotification = null;
|
Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
correctly.
- Single-line notifications that have _expandNotification() called (e.g.
because the user mouses over to them), are treated as expanded, which means
they get fully expanded if they are updated with more content and the user
can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
there after a notification is updated, even if it was previously hidden
because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
show it again.
- If a summary notification is updated while it is hiding, we let it finish
hiding and show a new notification with the updated information.
Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
means that their height matches the tray height, they are fully shown in the
banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
its expanded look when it is updated, and emits an 'expanded' signal
indicating that its layout has possibly changed. The message tray connects
to this 'expanded' signal when it is showing a notification in the expanded
state and updates the position of the notification accordingly when this
signal is received so that the notification is fully shown. This is better
than connecting to 'notify::height' signal on the notification bin, since
it results in fewer callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 19:47:12 +00:00
|
|
|
if (this._reNotifyWithSummaryNotificationAfterHide) {
|
|
|
|
this._onNotify(summaryNotification.source, summaryNotification);
|
|
|
|
this._reNotifyWithSummaryNotificationAfterHide = false;
|
|
|
|
}
|
2010-01-28 18:39:00 +00:00
|
|
|
}
|
2010-01-13 20:05:20 +00:00
|
|
|
};
|